diff --git a/.gitignore b/.gitignore
index f69985ef1f..120eedb7d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,5 @@ bin/
/text-ui-test/ACTUAL.txt
text-ui-test/EXPECTED-UNIX.TXT
+
+/data/
diff --git a/README.md b/README.md
index 698b938529..a756537f16 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-# Duke project template
+# Hospitalsaurus ReX project
-This is a project template for a greenfield Java project. It's named after the Java mascot _Duke_. Given below are instructions on how to use it.
+This is a Hospitalsaurus ReX project. Given below are instructions on how to use it.
## Setting up in Intellij
@@ -8,21 +8,25 @@ Prerequisites: JDK 11 (use the exact version), update Intellij to the most recen
1. **Configure Intellij for JDK 11**, as described [here](https://se-education.org/guides/tutorials/intellijJdk.html).
1. **Import the project _as a Gradle project_**, as described [here](https://se-education.org/guides/tutorials/intellijImportGradleProject.html).
-1. **Verify the set up**: After the importing is complete, locate the `src/main/java/seedu/duke/Duke.java` file, right-click it, and choose `Run Duke.main()`. If the setup is correct, you should see something like the below:
+1. **Verify the set up**: After the importing is complete, locate the `src/main/java/seedu/rex/Rex.java` file, right-click it, and choose `Run Rex.main()`. If the setup is correct, you should see something like the below:
```
- > Task :compileJava
+ > Task :compileJava UP-TO-DATE
> Task :processResources NO-SOURCE
- > Task :classes
+ > Task :classes UP-TO-DATE
- > Task :Duke.main()
- Hello from
- ____ _
- | _ \ _ _| | _____
- | | | | | | | |/ / _ \
- | |_| | |_| | < __/
- |____/ \__,_|_|\_\___|
-
- What is your name?
+ > Task :Rex.main()
+ ____________________________________________________________
+ _ _ _ _ _ _____ __ __
+ | | | | (_| | | | | __ \ \ \ / /
+ | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \ V /
+ | __ |/ _ \/ __| '_ \| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \ > <
+ | | | | (_) \__ | |_) | | || (_| | \__ | (_| | |_| | | | |_| \__ \ | | \ | __// . \
+ |_| |_|\___/|___| .__/|_|\__\__,_|_|___/\__,_|\__,_|_| \__,_|___/ |_| \_\___/_/ \_\
+ | |
+ |_|
+ How may i assist you?
+ ____________________________________________________________
+ Enter command:
```
Type some word and press enter to let the execution proceed to the end.
@@ -39,7 +43,7 @@ Prerequisites: JDK 11 (use the exact version), update Intellij to the most recen
### JUnit tests
-* A skeleton JUnit test (`src/test/java/seedu/duke/DukeTest.java`) is provided with this project template.
+* A skeleton JUnit test (`src/test/java/seedu/rex/RexTest.java`) is provided with this project template.
* If you are new to JUnit, refer to the [JUnit Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/junit.html).
## Checkstyle
diff --git a/build.gradle b/build.gradle
index b0c5528fb5..1d57a64eab 100644
--- a/build.gradle
+++ b/build.gradle
@@ -29,11 +29,11 @@ test {
}
application {
- mainClassName = "seedu.duke.Duke"
+ mainClassName = "seedu.rex.Rex"
}
shadowJar {
- archiveBaseName = "duke"
+ archiveBaseName = "rex"
archiveClassifier = null
}
@@ -43,4 +43,5 @@ checkstyle {
run{
standardInput = System.in
+ enableAssertions = true
}
diff --git a/docs/AboutUs.md b/docs/AboutUs.md
index 0f072953ea..18fdb4d624 100644
--- a/docs/AboutUs.md
+++ b/docs/AboutUs.md
@@ -1,9 +1,10 @@
# About us
+
Display | Name | Github Profile | Portfolio
--------|:----:|:--------------:|:---------:
- | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md)
- | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md)
- | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md)
- | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md)
- | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md)
+ | Tan Jun Hong | [Github](https://github.com/TanJunHong) | [Portfolio](team/tanjunhong.md)
+ | Liew You Sheng | [Github](https://github.com/GoldenCorgi) | [Portfolio](team/goldencorgi.md)
+ | Randy Ng | [Github](https://github.com/randynyl/) | [Portfolio](team/randynyl.md)
+ | Chong Yow Lim | [Github](https://github.com/ychong032) | [Portfolio](team/ychong032.md)
+ | Tan Kiat Hwe | [Github](https://github.com/kiathwe97) | [Portfolio](team/kiathwe97.md)
diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index 0ec3db103d..174539c17e 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -2,33 +2,175 @@
## Design & implementation
-{Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.}
+The app was mainly inspired by [addressbook-level2](https://github.com/se-edu/addressbook-level2).
+### Design
+The App consists of a few main components.
+
+* Ui: The UI that deals with getting user input and displaying output.
+* Command: Command to be executed.
+* Parser: Parse user input and make sense of it.
+* Storage: Reads data from, and writes data to, the hard disk.
+* Rex: The main class that initialize the app and starts running.
+
+The rest are just objects that the app requires.
+
+The diagram below shows the basic design.
+
+
+
+
+The complete class diagram is shown below.
+
+
+### Implementation
+The commands are implemented in such a way as we are able to have one class for every command, which allows for more extendability and less coupling, since we are likely to add more commands over time. We considered other alternatives such as putting all commands in one command class, however there are way too many methods and coupling.
+
+
+
+#### Retrieve Command
+The flow for the retrieve command is as follows:
+
+1. Retrieve command extracts NRIC using parser.
+2. Retrieve command searches through the patients list and obtains the patient's index.
+3. Patients list returns the patient.
+4. Ui object prints the patient.
+
+
+
+#### Add Command
+The flow for add command is as follows:
+
+1. Add command extracts NRIC by calling its own method.
+2. Add command checks patients list if NRIC already exists. Add command ends if so.
+3. Add command calls Ui object to get the patient name and date of birth from user.
+4. Patient list adds the new patient.
+5. Add command obtains the newly added patient.
+6. Ui receives the call to print the patient.
+7. The updated patients list is saved by the Storage object.
+
+
+
+#### Book Command
+The flow for the book command is shown in the sequence diagram below:
+
+1. Book command checks if there are available appointments.
+2. Book command extracts NRIC by calling its own method.
+3. Book command calls Ui to get the corresponding doctor name for the appointment.
+4. Book command calls Ui to get the selected appointment.
+5. The appointment is updated with the patient and doctor.
+6. Ui prints the booked appointment message.
+7. The updated appointments list is saved by Storage.
+
+
+
+#### Edit Command
+The flow for the edit command is shown in the sequence diagram below:
+
+
+
+
+#### Delete Patient Command
+The flow for the delete patient command is shown in the sequence diagram below:
+
+
+
## Product scope
### Target user profile
-{Describe the target user profile}
+Administrative staff of hospitals who are overworked from having various responsibilities with repetitive tasks relating to doctors and patients.
### Value proposition
-{Describe the value proposition: what problem does it solve?}
+Aim: To facilitate the role of the administrative staff and help them automate most of the mundane tasks that they have to do. This enables the admin staff to have a one stop application to handle appointments and fees across different specialised clinics in the hospital. Administrative staff will have more time to help patients or do things that are more meaningful, such as answering queries from patients or doctors.
## User Stories
|Version| As a ... | I want to ... | So that I can ...|
|--------|----------|---------------|------------------|
-|v1.0|new user|see usage instructions|refer to them when I forget how to use the application|
-|v2.0|user|find a to-do item by name|locate a to-do without having to go through the entire list|
+|v1.0|admin|enter patient's details and store it|refer to them whenever I require them.|
+|v1.0|admin|retrieve patient's details|use them to schedule appointments.|
+|v1.0|admin|remove existing patient's details|remove unnecessary information.|
+|v1.0|admin|view all appointments of a patient|remind patients of their appointments.|
+|v1.0|admin|book an appointment for a patient|let them see the doctor.|
+|v2.0|admin|add doctor|link doctor to appointment.|
+|v2.0|admin|remove existing doctor's details|remove unnecessary information.|
+|v2.0|admin|list patients|view patients.|
+|v2.0|admin|edit appointments|update them.|
## Non-Functional Requirements
-{Give non-functional requirements}
+* The program must be easy for admins to use.
+* The program must store patient's information.
+* The program must store doctor's information.
+* The program should run on any system running Java 11.
## Glossary
-* *glossary item* - Definition
+* *Hospitalsarus Rex* - The name of the program
+
+
## Instructions for manual testing
-{Give instructions on how to do a manual product testing e.g., how to load sample data to be used for testing}
+### Initial setup
+1. Download the jar file and copy it into an empty directory
+2. Open command prompt, and point it to that directory
+3. Type in `java -jar Rex.jar` to run the file
+
+
+### Adding a patient
+1. `add S9999999D` - Adds a patient with NRIC `S9999999D` to the list.
+2. `add S9999999D` - It should not add a patient and throw error as patient already exists.
+3. `add cat` - It should throw error and not add patients as it is invalid NRIC.
+
+
+### Edit a patient
+1. `edit S9999999D` - Edits a patient with NRIC `S9999999D`. More prompts will show to edit details
+2. `edit S9999998D` - It should not edit a patient and throw error as patient does not exist.
+
+
+### Retrieving a patient
+1. `retrieve S9999999D` - Retireve a patient's details with NRIC `S9999999D`.
+
+
+### Deleting a patient
+There must a patient in the list.
+1. `delete 1` - Deletes the patient at the first index
+2. `delete 0` - It should throw error and not delete a patient, since it is a invalid index.
+
+
+### Create appointment
+1. `create` - Creates an appointment. More prompts will show to prompt user about appointment.
+
+
+### Book appointment
+1. `book S9999999D` - Books an appointment for patient with NRIC `S9999999D`. More prompts will show to prompt user which appointment to book.
+
+
+### Adding a doctor
+1. `doctor tan` - Adds a doctor with name `tan` to the list.
+2. `doctor tan` - It should not add a doctor and throw error as doctor already exists.
+
+
+
+### Removing a doctor
+1. `nodoctor tan` - Removes doctor with name `tan` to the list.
+2. `nodoctor asd` - It should throw error and not delete a doctor since doctor does not exist.
+
+
+### View appointments of patient
+1. `appointments S9999999D` - Shows appointments for patient with NRIC `S9999999D`.
+
+
+### List patients
+1. `list` - Lists all patients.
+
+
+### Edit appointment
+1. `editappt S9999999D` - Edit appointment with NRIC `S9999999D`.
+
+
+### Exit program
+1. `bye` - Exits program.
diff --git a/docs/README.md b/docs/README.md
index bbcc99c1e7..690b93b82b 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,6 +1,6 @@
-# Duke
+# Hospitalsaurus ReX
-{Give product intro here}
+A hospital appointment log application for admins. Relieves admins on mundane tasks.
Useful links:
* [User Guide](UserGuide.md)
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index abd9fbe891..6316e68c61 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -2,41 +2,215 @@
## Introduction
-{Give a product intro}
+Hospitalsaurus ReX is a program to help administrative staff to keep track of patients.
## Quick Start
-{Give steps to get started quickly}
-
1. Ensure that you have Java 11 or above installed.
-1. Down the latest version of `Duke` from [here](http://link.to/duke).
+1. Download the latest version of `Hospitalsaurus ReX` from [here](https://github.com/AY2021S1-CS2113-T16-4/tp).
-## Features
+## Features
-{Give detailed description of each feature}
-### Adding a todo: `todo`
-Adds a new item to the list of todo items.
+### Adding a patient: `add`
+Adds a patient to the database.
-Format: `todo n/TODO_NAME d/DEADLINE`
+Format: `add NRIC`
-* The `DEADLINE` can be in a natural language format.
-* The `TODO_NAME` cannot contain punctuation.
+* The `NRIC` must be valid.
+* Program will prompt name and date of birth to be entered.
Example of usage:
-`todo n/Write the rest of the User Guide d/next week`
+`add S9922312D`
+
+`add S7423213Z`
+
+
+
+### Retrieve a patient: `retrieve`
+Retrieves a patient to the database.
+
+Format: `retrieve NRIC`
+
+* The `NRIC` must be valid and in the database.
+* Program will show name and date of birth of the patient.
+
+Example of usage:
+
+`retrieve S9922312D`
+
+`retrieve S7423213Z`
+
+
+### Edit a patient: `edit`
+Edits a patient to the database.
+
+Format: `edit NRIC`
+
+* The `NRIC` must be valid and in the database.
+* Program will prompt name and date of birth to be edited.
+
+Example of usage:
+
+`edit S9922312D`
+
+`edit S7423213Z`
+
+
+### Delete a patient: `delete`
+Deletes a patient to the database.
+
+Format: `delete NRIC`
+
+* The `NRIC` must be valid and in the database.
+* Program will delete patient with nric as `NRIC`.
+
+Example of usage:
+
+`delete S9922312D`
+
+`delete S7423213Z`
+
+
+
+### Create an appointment: `create`
+Creates an appointment date.
+
+Format: `create`
+
+* Program will prompt for date to be inputted.
+
+Example of usage:
+
+`create`
+
+
+### Book an appointment: `book`
+Books an appointment date.
+
+Format: `book NRIC`
+
+* The `NRIC` should be valid and in the database, else `add` command will run
+* Program will show a lists of available dates and prompt for which date to use.
+
+Example of usage:
+
+`book S9922312D`
+
+`book S7423213Z`
+
+
+### Add a doctor: `doctor`
+Adds a doctor.
+
+Format: `doctor NAME`
+
+* The `NAME` should not already be inside the list.
+
+Example of usage:
+
+`doctor tan`
+
+`doctor trump`
+
+
+
+### Remove a doctor: `doctor`
+Remove a doctor.
+
+Format: `nodoctor NAME`
+
+* The `NAME` should be in the list.
+
+Example of usage:
+
+`nodoctor tan`
+
+`nodoctor trump`
+
+
+### View patient's appointments: `appointments`
+View patient's appointments
+
+Format: `appointments NRIC`
+
+* The `NRIC` should be valid and in the list.
+
+Example of usage:
+
+`appointments S2233445D`
+
+`appointments S1234556F`
+
+
+### List patients: `list`
+View patient's appointments
+
+Format: `list`
+
+* The patient list should not be empty.
+
+Example of usage:
+
+`list`
+
+
+
+### Edit patient's appointment: `editappt`
+Edit patient's appointment
+
+Format: `editappt NRIC`
+
+* The patient with `NRIC` should already exist.
+* The program will prompt user to select the booked appointment to be replaced, the new appointment to be booked, and the doctor to be in charge.
+
+Example of usage:
+
+`editappt S9900999D`
+
+`editappt S9900299D`
+
+
+### Exit program: `bye`
+Exit the program
+
+Format: `bye`
+
+* The program will miss you.
+
+Example of usage:
+
+`bye`
-`todo n/Refactor the User Guide to remove passive voice d/13/04/2020`
## FAQ
**Q**: How do I transfer my data to another computer?
-**A**: {your answer here}
+**A**: Clone the program to the other computer, and copy the data folder over.
-## Command Summary
+**Q**: Why is the name Hospitalsaurus Rex?
-{Give a 'cheat sheet' of commands here}
+**A**: Because we are nerds.
+
+**Q**: How do I request for more features?
+
+**A**: Contact us.
+
+
+
+## Command Summary
-* Add todo `todo n/TODO_NAME d/DEADLINE`
+* Add patient `add NRIC`
+* Retrieve patient `retrieve NRIC`
+* Edit patient `edit NRIC`
+* Delete patient `delete NRIC`
+* Create appointment `create`
+* Book appointment `book NRIC`
+* Add doctor `doctor NAME`
+* Remove doctor `nodoctor NAME`
+* View appointments of a patient `appointments NRIC`
+* List patients `list`
+* Edit patient's appointment `editappt NRIC`
+* Exit `bye`
diff --git a/docs/_config.yml b/docs/_config.yml
new file mode 100644
index 0000000000..18854876c6
--- /dev/null
+++ b/docs/_config.yml
@@ -0,0 +1 @@
+theme: jekyll-theme-midnight
\ No newline at end of file
diff --git a/docs/pictures/DeletePatientCD.png b/docs/pictures/DeletePatientCD.png
new file mode 100644
index 0000000000..266f5cf5e2
Binary files /dev/null and b/docs/pictures/DeletePatientCD.png differ
diff --git a/docs/pictures/DeletePatientSeqDiagram.png b/docs/pictures/DeletePatientSeqDiagram.png
new file mode 100644
index 0000000000..5f61af8f38
Binary files /dev/null and b/docs/pictures/DeletePatientSeqDiagram.png differ
diff --git a/docs/pictures/DeletePatientSeqDiagram.puml b/docs/pictures/DeletePatientSeqDiagram.puml
new file mode 100644
index 0000000000..7bb8dc40ba
--- /dev/null
+++ b/docs/pictures/DeletePatientSeqDiagram.puml
@@ -0,0 +1,123 @@
+@startuml
+Create ui
+Rex --> ui
+
+Create storage
+Rex --> storage
+
+Create patients
+Rex --> patients
+
+Create appointments
+Rex --> appointments
+
+Create parser
+Rex --> parser
+
+
+
+Activate Rex
+Rex --> Rex : run()
+Activate Rex
+Activate ui
+loop !isExit
+ Rex --> ui : readCommand()
+ ui --> Rex
+ Deactivate ui
+
+ Rex --> ui : showLine()
+ Rex --> parser : parse(fullCommand)
+ Activate parser
+ Create deletePatientCommand
+ parser --> deletePatientCommand
+ parser --> Rex : Command c
+ Deactivate parser
+ parser --> deletePatientCommand : execute(patients, doctors, appointments, ui, storage)
+ Activate deletePatientCommand
+ deletePatientCommand --> deletePatientCommand : extractNric(trimmedCommand, COMMAND_WORD)
+ Activate deletePatientCommand
+ deletePatientCommand --> deletePatientCommand : String nric
+ Deactivate deletePatientCommand
+
+ deletePatientCommand --> patients : deletePatient(nric)
+ Activate patients
+ patients --> deletePatientCommand : Patient deletedPatient
+ Deactivate patients
+
+ deletePatientCommand --> ui : showPatientDeleted(deletedPatient)
+ Activate ui
+ Deactivate ui
+
+ loop i=0; i appointments : getappointmentByIndex(i)
+ Activate appointments
+ appointments --> deletePatientCommand : Appointment appointment
+ Deactivate appointments
+ alt appointment.getPatient().getNric() == nric.toLowerCase()
+ deletePatientCommand --> appointment : setPatient(null)
+ Activate appointment
+ Deactivate appointment
+
+ deletePatientCommand --> appointment : removeBooking()
+ Activate appointment
+ Deactivate appointment
+
+ deletePatientCommand --> appointment : setDoctor(null)
+ Activate appointment
+ Deactivate appointment
+ else
+ deletePatientCommand --> ui : printPatientNotFound(nric)
+ Activate ui
+ Deactivate ui
+ deletePatientCommand --> storage : savePatients(patients)
+ Activate storage
+ Deactivate storage
+
+ deletePatientCommand --> storage : saveappointments(patients)
+ Activate storage
+ Deactivate storage
+
+
+
+
+
+end loop
+
+
+
+
+@enduml
+
+alt words[0] == ExitCommand.COMMAND_WORD
+ Create ExitCommand
+ parser --> ExitCommand : new
+ else words[0] == BookApptCommand.COMMAND_WORD
+ Create BookApptCommand
+ parser --> BookApptCommand : new
+ else words[0] == AddPatientCommand.COMMAND_WORD
+ Create AddPatientCommand
+ parser --> AddPatientCommand : new
+ else words[0] == CreateApptCommand.COMMAND_WORD
+ Create CreateApptCommand
+ parser --> CreateApptCommand : new
+ else words[0] == EditPatientCommand.COMMAND_WORD
+ Create EditPatientCommand
+ parser --> EditPatientCommand : new
+ else words[0] == deletePatientCommand.COMMAND_WORD
+ Create deletePatientCommand
+ parser --> deletePatientCommand : new
+ else words[0] == ListApptCommand.COMMAND_WORD
+ Create ListApptCommand
+ parser --> ListApptCommand : new
+ else words[0] == ListPatientCommand.COMMAND_WORD
+ Create ListPatientCommand
+ parser --> ListPatientCommand : new
+ else words[0] == RetrievePatientCommand.COMMAND_WORD
+ Create RetrievePatientCommand
+ parser --> RetrievePatientCommand : new
+ else words[0] == AddDoctorCommand.COMMAND_WORD
+ Create AddDoctorCommand
+ parser --> AddDoctorCommand : new
+ else words[0] == EditApptCommand.COMMAND_WORD
+ Create EditApptCommand
+ parser --> EditApptCommand : new
\ No newline at end of file
diff --git a/docs/pictures/KiatHwe.puml b/docs/pictures/KiatHwe.puml
new file mode 100644
index 0000000000..4988c2e7e6
--- /dev/null
+++ b/docs/pictures/KiatHwe.puml
@@ -0,0 +1,28 @@
+@startuml
+Command <|-- DeletePatientCommand
+
+Command : {static} String MESSAGE
+Command : {static} String COMMAND_ERROR
+Command : {static} int LEGAL_NRIC_LENGTH
+Command : {static} Set LEGAL_NRIC_STATUSES
+
+Command : + Command()
+Command : + {abstract} execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) : void
+Command : + isExit() : boolean
+Command : + isInteger() : boolean
+Command : + extractNric(String trimmedCommand, String commandWord) : String
+
+DeletePatientCommand : {static} String COMMAND_WORD
+DeletePatientCommand : String trimmedCommand
+
+DeletePatientCommand : DeletePatientCommand(String trimmedCommand)
+DeletePatientCommand : execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) : void
+
+DeletePatientCommand ..> PatientList
+DeletePatientCommand ..> DoctorList
+DeletePatientCommand ..> AppointmentList
+DeletePatientCommand ..> Ui
+DeletePatientCommand ..> Storage
+
+
+@enduml
\ No newline at end of file
diff --git a/docs/pictures/UML.png b/docs/pictures/UML.png
new file mode 100644
index 0000000000..adc652c0f6
Binary files /dev/null and b/docs/pictures/UML.png differ
diff --git a/docs/pictures/UMLEdit.png b/docs/pictures/UMLEdit.png
new file mode 100644
index 0000000000..cfcbddd1ed
Binary files /dev/null and b/docs/pictures/UMLEdit.png differ
diff --git a/docs/pictures/addCommandSD.PNG b/docs/pictures/addCommandSD.PNG
new file mode 100644
index 0000000000..4cf360819f
Binary files /dev/null and b/docs/pictures/addCommandSD.PNG differ
diff --git a/docs/pictures/bookCommandSD.PNG b/docs/pictures/bookCommandSD.PNG
new file mode 100644
index 0000000000..eeb0079c42
Binary files /dev/null and b/docs/pictures/bookCommandSD.PNG differ
diff --git a/docs/pictures/classDiagram.PNG b/docs/pictures/classDiagram.PNG
new file mode 100644
index 0000000000..dcdc065f55
Binary files /dev/null and b/docs/pictures/classDiagram.PNG differ
diff --git a/docs/pictures/retrieveCommandSD.png b/docs/pictures/retrieveCommandSD.png
new file mode 100644
index 0000000000..7df36639a4
Binary files /dev/null and b/docs/pictures/retrieveCommandSD.png differ
diff --git a/docs/team/goldencorgi.md b/docs/team/goldencorgi.md
new file mode 100644
index 0000000000..f3ad8a63d0
--- /dev/null
+++ b/docs/team/goldencorgi.md
@@ -0,0 +1,14 @@
+# Liew You Sheng - Project Portfolio Page
+
+## Overview
+A hospital appointment log application for admins. Relieves admins on mundane tasks.
+
+### Summary of Contributions
+* [Code contributed](https://nus-cs2113-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=goldencorgi)
+* Enhancements implemented:
+ * Improved code quality
+ * General code cleanup
+* Contributions to the DG:
+ * Retrieve edit sequence diagram
+* Ability to edit patients information using NRIC
+* Ability to edit and remove appointments
diff --git a/docs/team/johndoe.md b/docs/team/johndoe.md
deleted file mode 100644
index ab75b391b8..0000000000
--- a/docs/team/johndoe.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# John Doe - Project Portfolio Page
-
-## Overview
-
-
-### Summary of Contributions
diff --git a/docs/team/kiathwe97.md b/docs/team/kiathwe97.md
new file mode 100644
index 0000000000..81b7dd6a28
--- /dev/null
+++ b/docs/team/kiathwe97.md
@@ -0,0 +1,14 @@
+# Tan Kiat Hwe - Project Portfolio Page
+
+## Overview
+A hospital appointment log application for admins. Relieves admins on mundane tasks.
+
+Given below is a summary of my contributions.
+### Summary of Contributions
+* [Code contributed](https://nus-cs2113-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=kiathwe97)
+* Enhancements implemented:
+ * Junit Test for Deleting Patient
+ * Improved code quality
+* Contributions to the DG:
+ * Sequence Diagram for Deleting Patient
+* Ability to delete patient using NRIC and the appointments that are booked by that particular patient
diff --git a/docs/team/randynyl.md b/docs/team/randynyl.md
new file mode 100644
index 0000000000..90deb9a723
--- /dev/null
+++ b/docs/team/randynyl.md
@@ -0,0 +1,16 @@
+# Randy Ng - Project Portfolio Page
+
+## Overview
+A hospital appointment log application for admins. Relieves admins on mundane tasks.
+
+### Summary of Contributions
+* [Code contributed](https://nus-cs2113-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=randynyl)
+* Enhancements implemented:
+ * Ability to create appointments
+ * Ability to book appointments
+ * Improved code quality
+ * Some JUnit tests
+* Contributions to the DG:
+ * Complete class diagram
+ * Book command sequence diagram and flow
+
diff --git a/docs/team/tanjunhong.md b/docs/team/tanjunhong.md
new file mode 100644
index 0000000000..e29b54456e
--- /dev/null
+++ b/docs/team/tanjunhong.md
@@ -0,0 +1,31 @@
+# Tan Jun Hong - Project Portfolio Page
+
+## Overview
+A hospital appointment log application for admins. Relieves admins on mundane tasks.
+
+### Summary of Contributions
+* [Code contributed](https://nus-cs2113-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=tanjunhong)
+* Enhancements implemented:
+ * Improved code quality
+ * General code cleanup
+* Contributions to documentation:
+ * Created the introduction section
+ * Created the Quick start section
+ * Created features section
+ * Created FAQ section
+ * Created commands Summary
+* Contributions to the DG:
+ * Added design
+ * Retrieve command sequence diagram
+ * Product scope section
+ * User stories section
+ * NFRs section
+ * Glossary section
+ * Instructions for manual testing section
+* Contributions to team-tasks
+ * Setting up the GitHub team org/repo
+ * Maintaining the issue tracker
+ * Release management
+* Ability to retrieve patients information using NRIC
+* Add and remove doctor function
+* Most of JUnit, Logging and Assertions
diff --git a/docs/team/ychong032.md b/docs/team/ychong032.md
new file mode 100644
index 0000000000..9088a5a9ab
--- /dev/null
+++ b/docs/team/ychong032.md
@@ -0,0 +1,18 @@
+# Chong Yow Lim - Project Portfolio Page
+
+## Overview
+A hospital appointment log application for admins. Relieves admins on mundane tasks.
+
+Given below is a summary of my contributions.
+### Summary of Contributions
+* [Code contributed](https://nus-cs2113-ay2021s1.github.io/tp-dashboard/#breakdown=true&search=ychong032)
+ * Added ability to add new patients
+ * Handled user input errors
+* Enhancements implemented:
+ * Improved code quality
+* Contributions to documentation:
+ * Amended typos and completed missing information
+* Contributions to the DG:
+ * Amended retrieve command sequence diagram
+ * Amended retrieve command flow
+ * Created add command sequence diagram and flow
diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java
deleted file mode 100644
index 5c74e68d59..0000000000
--- a/src/main/java/seedu/duke/Duke.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package seedu.duke;
-
-import java.util.Scanner;
-
-public class Duke {
- /**
- * Main entry-point for the java.duke.Duke application.
- */
- public static void main(String[] args) {
- String logo = " ____ _ \n"
- + "| _ \\ _ _| | _____ \n"
- + "| | | | | | | |/ / _ \\\n"
- + "| |_| | |_| | < __/\n"
- + "|____/ \\__,_|_|\\_\\___|\n";
- System.out.println("Hello from\n" + logo);
- System.out.println("What is your name?");
-
- Scanner in = new Scanner(System.in);
- System.out.println("Hello " + in.nextLine());
- }
-}
diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java
new file mode 100644
index 0000000000..974af1aaea
--- /dev/null
+++ b/src/main/java/seedu/rex/Rex.java
@@ -0,0 +1,113 @@
+package seedu.rex;
+
+import seedu.rex.commands.Command;
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.parser.Parser;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Main class.
+ */
+public class Rex {
+
+ public static Logger logger;
+ private static PatientList patients;
+ private static DoctorList doctors;
+ private final Storage storage;
+ private final Ui ui;
+ private AppointmentList appointments;
+
+ /**
+ * Initializes Rex.
+ *
+ * @param filePath Path to store and load patients.
+ */
+ public Rex(String filePath) {
+ assert filePath != null && !filePath.equals("") : "File path cannot be empty!";
+
+ ui = new Ui();
+ storage = new Storage(filePath);
+ logger = Logger.getLogger("Rex");
+ logger.setLevel(Level.WARNING);
+
+ try {
+ logger.log(Level.INFO, "going to load patients");
+ patients = new PatientList(storage.loadPatients());
+ logger.log(Level.INFO, "loaded patients");
+ } catch (RexException e) {
+ logger.log(Level.INFO, "No patients found. Creating new patients list.");
+ ui.showLoadingError();
+ patients = new PatientList();
+ }
+
+ try {
+ logger.log(Level.INFO, "going to load doctors");
+ doctors = new DoctorList(storage.loadDoctors());
+ logger.log(Level.INFO, "loaded doctors");
+ } catch (RexException e) {
+ logger.log(Level.INFO, "No doctors found. Creating new doctors list.");
+ ui.showLoadingError();
+ doctors = new DoctorList();
+ }
+
+ try {
+ logger.log(Level.INFO, "going to load appointments");
+ appointments = new AppointmentList(storage.loadAppointments());
+ logger.log(Level.INFO, "loaded appointments");
+ } catch (RexException e) {
+ logger.log(Level.INFO, "No appointments found. Creating new appointments list.");
+ ui.showLoadingError();
+ appointments = new AppointmentList();
+ }
+ }
+
+ /**
+ * Starts Rex.
+ *
+ * @param args Command line argument.
+ */
+ public static void main(String[] args) {
+ new Rex("data").run();
+ }
+
+ public static PatientList getPatients() {
+ return patients;
+ }
+
+ public static DoctorList getDoctors() {
+ return doctors;
+ }
+
+ /**
+ * Runs Rex.
+ */
+ public void run() {
+ assert ui != null : "ui is null";
+ assert patients != null : "patient ArrayList is null";
+ assert doctors != null : "patient ArrayList is null";
+ assert storage != null : "storage is null";
+
+ ui.showWelcome();
+ boolean isExit = false;
+ while (!isExit) {
+ try {
+ String fullCommand = ui.readCommand();
+ ui.showLine();
+ Command c = Parser.parse(fullCommand);
+ c.execute(patients, doctors, appointments, ui, storage);
+ isExit = c.isExit();
+ } catch (RexException e) {
+ ui.showError(e.getMessage());
+ } finally {
+ ui.showLine();
+ }
+ }
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/AddDoctorCommand.java b/src/main/java/seedu/rex/commands/AddDoctorCommand.java
new file mode 100644
index 0000000000..7b1069b52a
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/AddDoctorCommand.java
@@ -0,0 +1,50 @@
+package seedu.rex.commands;
+
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Doctor;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+/**
+ * Adds doctor to DoctorList.
+ */
+public class AddDoctorCommand extends Command {
+ public static final String COMMAND_WORD = "doctor";
+ private final String trimmedCommand;
+
+ public AddDoctorCommand(String trimmedCommand) {
+ this.trimmedCommand = trimmedCommand;
+ }
+
+ /**
+ * Adds doctor with name.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object.
+ * @param storage Storage object.
+ * @throws RexException If there is issue executing command.
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage)
+ throws RexException {
+
+ String doctorName = trimmedCommand.replaceFirst("(?i)" + COMMAND_WORD, "").trim().toUpperCase();
+
+ if (doctors.isExistingDoctor(doctorName)) {
+ throw new RexException("A doctor with this name is already registered!");
+ }
+
+ Doctor newDoctor = new Doctor(doctorName);
+ doctors.addDoctor(newDoctor);
+
+ ui.showDoctorAdded(newDoctor);
+
+ assert !doctors.getDoctors().isEmpty() : "No doctors!";
+ storage.saveDoctors(doctors);
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/AddPatientCommand.java b/src/main/java/seedu/rex/commands/AddPatientCommand.java
new file mode 100644
index 0000000000..5245509771
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/AddPatientCommand.java
@@ -0,0 +1,58 @@
+package seedu.rex.commands;
+
+import seedu.rex.Rex;
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+import java.util.logging.Level;
+
+/**
+ * Adds a patient to the list of patients.
+ */
+public class AddPatientCommand extends Command {
+
+ public static final String COMMAND_WORD = "add";
+ private final String trimmedCommand;
+
+ public AddPatientCommand(String trimmedCommand) {
+ this.trimmedCommand = trimmedCommand;
+ }
+
+ /**
+ * Adds a new patient to the patient list using details inputted by the user.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object of the program.
+ * @param storage Storage object used for saving data to files.
+ * @throws RexException If there is an error in the NRIC inputted by the user, the data fails
+ * to save successfully, or the NRIC already exists in the patient list.
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage)
+ throws RexException {
+ assert patients != null : "patient ArrayList is null";
+ assert ui != null : "ui is null";
+ assert storage != null : "storage is null";
+ Rex.logger.log(Level.INFO, "going to extract NRIC");
+ String nric = extractNric(trimmedCommand, COMMAND_WORD);
+
+ if (patients.isExistingPatient(nric)) {
+ throw new RexException("A patient with this NRIC is already registered!");
+ }
+
+ Rex.logger.log(Level.INFO, "adding patient...");
+ patients.addNewPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth());
+ ui.showLine();
+
+ ui.showPatientAdded(patients.getPatientUsingIndex(patients.getSize() - 1));
+
+ assert !patients.getPatients().isEmpty() : "No patients!";
+ storage.savePatients(patients);
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/BookApptCommand.java b/src/main/java/seedu/rex/commands/BookApptCommand.java
new file mode 100644
index 0000000000..c918138768
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/BookApptCommand.java
@@ -0,0 +1,77 @@
+package seedu.rex.commands;
+
+import seedu.rex.Rex;
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Appointment;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+import java.util.logging.Level;
+
+/**
+ * Books appointments.
+ */
+public class BookApptCommand extends Command {
+
+ public static final String COMMAND_WORD = "book";
+ private final String trimmedCommand;
+
+ public BookApptCommand(String trimmedCommand) {
+ this.trimmedCommand = trimmedCommand;
+ }
+
+ /**
+ * Books appointment for patients.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object.
+ * @param storage Storage object.
+ * @throws RexException If appointment cannot be booked.
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage)
+ throws RexException {
+
+ assert patients != null : "patient ArrayList is null";
+ assert ui != null : "ui is null";
+ assert storage != null : "storage is null";
+
+ if (appointments.isEmpty()) {
+ throw new RexException("No appointment sessions!");
+ }
+
+ Rex.logger.log(Level.INFO, "going to extract NRIC");
+ String nric = extractNric(trimmedCommand, COMMAND_WORD);
+
+ Rex.logger.log(Level.INFO, "going to get doctor's name");
+ String doctorName = ui.getDoctorName();
+ if (!doctors.isExistingDoctor(doctorName)) {
+ throw new RexException("No such doctor!");
+ }
+
+ if (!patients.isExistingPatient(nric)) {
+ throw new RexException("Patient " + nric + " not found in database!");
+ }
+
+ try {
+ ui.showAvailableAppointmentsMessage();
+ Rex.logger.log(Level.INFO, "booking appointment for patient and doctor...");
+ Appointment chosenAppointment = ui.getItemOfArrayList(appointments.getAvailableAppointments());
+ chosenAppointment.bookPatient(patients.getPatientFromNric(nric));
+ chosenAppointment.bookDoctor(doctors.getDoctorFromName(doctorName));
+ ui.showAppointmentBookedMessage(chosenAppointment);
+
+ assert !appointments.isEmpty() : "No appointments!";
+ storage.saveAppointments(appointments);
+ } catch (NumberFormatException e) {
+ throw new RexException("Index error!");
+ }
+
+
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java
new file mode 100644
index 0000000000..8de7b35804
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/Command.java
@@ -0,0 +1,95 @@
+package seedu.rex.commands;
+
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+import java.util.Set;
+
+/**
+ * Parent Command class.
+ */
+public abstract class Command {
+
+ public static final String MESSAGE = String.join(System.lineSeparator(), Ui.LOGO, "How may i assist you?");
+ public static final String COMMAND_ERROR = "I'm sorry, but I don't know what that means :-(";
+ public static final int LEGAL_NRIC_LENGTH = 9;
+ public static final Set LEGAL_NRIC_STATUSES = Set.of('S', 'T', 'F', 'G');
+
+ boolean isExit;
+
+ /**
+ * Initializes command to execute and set exit status to false.
+ */
+ public Command() {
+ isExit = false;
+ }
+
+ /**
+ * Executes command.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object.
+ * @param storage Storage object.
+ * @throws RexException If there is issue executing command.
+ */
+ public abstract void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui,
+ Storage storage) throws RexException;
+
+ /**
+ * Returns Rex's exit status.
+ *
+ * @return Exit status.
+ */
+ public boolean isExit() {
+ return isExit;
+ }
+
+ /**
+ * Checks if a given String consists of only integer characters.
+ *
+ * @param string The String to be checked.
+ * @return true if the string contains only integer characters; false otherwise.
+ */
+ public boolean isInteger(String string) {
+ if (string == null) {
+ return false;
+ }
+ try {
+ Integer.parseInt(string);
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Extracts the NRIC from command inputted by the user.
+ *
+ * @param trimmedCommand Command that was trimmed.
+ * @param commandWord Command that was called.
+ * @return Patient's NRIC as a String.
+ * @throws RexException If the NRIC inputted by the user is invalid.
+ */
+ public String extractNric(String trimmedCommand, String commandWord) throws RexException {
+ String nric = trimmedCommand.replaceFirst("(?i)" + commandWord, "").trim().toUpperCase();
+ if (nric.isBlank()) {
+ throw new RexException("Please enter a valid NRIC after '" + commandWord + "'.");
+ } else if (nric.length() != LEGAL_NRIC_LENGTH) {
+ throw new RexException("Invalid NRIC length!");
+ } else if (!LEGAL_NRIC_STATUSES.contains(nric.charAt(0))) {
+ throw new RexException("Beginning character of NRIC must be 'S', 'T', 'F', or 'G'!");
+ } else if (!isInteger(nric.substring(1, LEGAL_NRIC_LENGTH - 1))) {
+ throw new RexException("Number sequence of NRIC is invalid!");
+ } else if (!Character.isLetter(nric.charAt(nric.length() - 1))) {
+ throw new RexException("Final character of NRIC must be an English alphabet!");
+ } else {
+ return nric;
+ }
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/CreateApptCommand.java b/src/main/java/seedu/rex/commands/CreateApptCommand.java
new file mode 100644
index 0000000000..c08b053cd8
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/CreateApptCommand.java
@@ -0,0 +1,51 @@
+package seedu.rex.commands;
+
+import seedu.rex.Rex;
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Appointment;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeParseException;
+import java.util.logging.Level;
+
+/**
+ * Creates appointment.
+ */
+public class CreateApptCommand extends Command {
+
+ public static final String COMMAND_WORD = "create";
+
+
+ /**
+ * Creates appointment using date given.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object.
+ * @param storage Storage object.
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui,
+ Storage storage) throws RexException {
+ assert patients != null : "patient ArrayList is null";
+ assert ui != null : "ui is null";
+ assert storage != null : "storage is null";
+ Rex.logger.log(Level.INFO, "going to create appointment");
+ String date = ui.getNewAppointmentDate();
+ try {
+ Appointment newAppointment = new Appointment(LocalDate.parse(date));
+ appointments.addAppointment(newAppointment);
+ ui.showAppointmentCreatedMessage();
+
+ } catch (DateTimeParseException e) {
+ ui.showDateInputError();
+ }
+ storage.saveAppointments(appointments);
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/DeleteApptCommand.java b/src/main/java/seedu/rex/commands/DeleteApptCommand.java
new file mode 100644
index 0000000000..3a13163e32
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/DeleteApptCommand.java
@@ -0,0 +1,71 @@
+package seedu.rex.commands;
+
+import seedu.rex.Rex;
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Appointment;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+import java.util.ArrayList;
+import java.util.logging.Level;
+
+/**
+ * Deletes appointment.
+ */
+public class DeleteApptCommand extends Command {
+
+ public static final String COMMAND_WORD = "deleteappt";
+ private final String trimmedCommand;
+
+
+ public DeleteApptCommand(String trimmedCommand) {
+ this.trimmedCommand = trimmedCommand;
+ }
+
+ /**
+ * Deletes appointment using NRIC given.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object.
+ * @param storage Storage object.
+ * @throws RexException If the input NRIC does not exist in system
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui,
+ Storage storage) throws RexException {
+ assert patients != null : "patient ArrayList is null";
+ assert ui != null : "ui is null";
+ assert storage != null : "storage is null";
+ Rex.logger.log(Level.INFO, "going to extract NRIC");
+ String nric = extractNric(trimmedCommand, COMMAND_WORD);
+
+ if (!patients.isExistingPatient(nric)) {
+ throw new RexException("A patient with this NRIC has not been registered!");
+ }
+
+ try {
+ ArrayList patientAppointments = new ArrayList<>();
+ for (int i = 0; i < appointments.getSize(); i++) {
+ if (appointments.getAppointmentByIndex(i).getPatient() != null
+ && appointments.getAppointmentByIndex(i).getPatient().getNric().equals(nric)) {
+ patientAppointments.add(appointments.getAppointmentByIndex(i));
+ }
+ }
+ ui.showDeleteAppointmentMessage();
+ Appointment appointmentToEdit = ui.getItemOfArrayList(patientAppointments);
+ ui.showDeleteAppointmentMessage(appointmentToEdit);
+ appointmentToEdit.removeBooking();
+
+ assert !appointments.isEmpty() : "No appointments!";
+ storage.saveAppointments(appointments);
+ } catch (NumberFormatException e) {
+ throw new RexException("Index error!");
+ }
+
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java b/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java
new file mode 100644
index 0000000000..9bd8a947e6
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java
@@ -0,0 +1,62 @@
+package seedu.rex.commands;
+
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Doctor;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+/**
+ * Deletes doctor.
+ */
+public class DeleteDoctorCommand extends Command {
+ public static final String COMMAND_WORD = "nodoctor";
+ private final String trimmedCommand;
+
+ public DeleteDoctorCommand(String trimmedCommand) {
+ this.trimmedCommand = trimmedCommand;
+ }
+
+ /**
+ * Executes command.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object.
+ * @param storage Storage object.
+ * @throws RexException If there is issue executing command.
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage)
+ throws RexException {
+
+ String doctorName = trimmedCommand.replaceFirst("(?i)" + COMMAND_WORD, "").trim().toUpperCase();
+
+ if (doctors.isExistingDoctor(doctorName)) {
+ Doctor deletedDoctor = doctors.deleteDoctor(doctorName);
+ assert deletedDoctor != null : "Deleted doctor is null!";
+
+ ui.showDoctorDeleted(deletedDoctor);
+
+ for (int i = 0; i < appointments.getSize(); i++) {
+ if (appointments.getAppointmentByIndex(i).getDoctor() == null) {
+ continue;
+ }
+ String tempName = appointments.getAppointmentByIndex(i).getDoctor().getName();
+ if (tempName.equals(doctorName)) {
+ appointments.getAppointmentByIndex(i).setPatient(null);
+ appointments.getAppointmentByIndex(i).removeBooking();
+ appointments.getAppointmentByIndex(i).setDoctor(null);
+ break;
+ }
+ }
+ } else {
+ ui.printDoctorNotFound(doctorName);
+ }
+ storage.saveAppointments(appointments);
+ storage.saveDoctors(doctors);
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/DeletePatientCommand.java b/src/main/java/seedu/rex/commands/DeletePatientCommand.java
new file mode 100644
index 0000000000..c0144e652c
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/DeletePatientCommand.java
@@ -0,0 +1,65 @@
+package seedu.rex.commands;
+
+import seedu.rex.Rex;
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Patient;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+import java.util.logging.Level;
+
+/**
+ * Deletes a Patient's data based on his NRIC.
+ */
+public class DeletePatientCommand extends Command {
+ public static final String COMMAND_WORD = "delete";
+ private final String trimmedCommand;
+
+ public DeletePatientCommand(String trimmedCommand) {
+ this.trimmedCommand = trimmedCommand;
+ }
+
+ /**
+ * Deletes patients using NRIC.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object.
+ * @param storage Storage object.
+ * @throws RexException If NRIC has issues.
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage)
+ throws RexException {
+ assert patients != null : "patient ArrayList is null";
+ assert ui != null : "ui is null";
+ assert storage != null : "storage is null";
+ Rex.logger.log(Level.INFO, "going to extract NRIC");
+ String nric = extractNric(trimmedCommand, COMMAND_WORD);
+
+ if (patients.isExistingPatient(nric)) {
+ Patient deletedPatient = patients.deletePatient(nric);
+ assert deletedPatient != null : "Deleted patient is null!";
+
+ ui.showPatientDeleted(deletedPatient);
+
+ for (int i = 0; i < appointments.getSize(); i++) {
+ Patient tempPatient = appointments.getAppointmentByIndex(i).getPatient();
+ if (tempPatient != null && tempPatient.getNric().contentEquals(nric)) {
+ appointments.getAppointmentByIndex(i).setPatient(null);
+ appointments.getAppointmentByIndex(i).removeBooking();
+ appointments.getAppointmentByIndex(i).setDoctor(null);
+ break;
+ }
+ }
+ } else {
+ ui.printPatientNotFound(nric);
+ }
+ storage.savePatients(patients);
+ storage.saveAppointments(appointments);
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/EditApptCommand.java b/src/main/java/seedu/rex/commands/EditApptCommand.java
new file mode 100644
index 0000000000..ece122eb20
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/EditApptCommand.java
@@ -0,0 +1,86 @@
+package seedu.rex.commands;
+
+import seedu.rex.Rex;
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Appointment;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+import java.util.ArrayList;
+import java.util.logging.Level;
+
+/**
+ * Edits appointment.
+ */
+public class EditApptCommand extends Command {
+
+ public static final String COMMAND_WORD = "editappt";
+ private final String trimmedCommand;
+
+
+ public EditApptCommand(String trimmedCommand) {
+ this.trimmedCommand = trimmedCommand;
+ }
+
+ /**
+ * Edits appointment using NRIC given.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object.
+ * @param storage Storage object.
+ * @throws RexException If the input NRIC does not exist in system
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui,
+ Storage storage) throws RexException {
+ assert patients != null : "patient ArrayList is null";
+ assert ui != null : "ui is null";
+ assert storage != null : "storage is null";
+ Rex.logger.log(Level.INFO, "going to extract NRIC");
+ String nric = extractNric(trimmedCommand, COMMAND_WORD);
+
+ if (!patients.isExistingPatient(nric)) {
+ throw new RexException("A patient with this NRIC has not been registered!");
+ }
+
+ try {
+ ArrayList patientAppointments = new ArrayList<>();
+ for (int i = 0; i < appointments.getSize(); i++) {
+ if (appointments.getAppointmentByIndex(i).getPatient() != null
+ && appointments.getAppointmentByIndex(i).getPatient().getNric().equals(nric)) {
+ patientAppointments.add(appointments.getAppointmentByIndex(i));
+ }
+ }
+ ui.showEditAppointmentMessage();
+ Appointment appointmentToEdit = ui.getItemOfArrayList(patientAppointments);
+ ui.showDeleteAppointmentMessage(appointmentToEdit);
+ appointmentToEdit.removeBooking();
+
+ String indexSelected = ui.getAppointmentToEdit(appointments);
+ int index = Integer.parseInt(indexSelected) - 1;
+ if (index < 0 || index >= appointments.getSize()) {
+ throw new RexException("Index error!");
+ }
+ Rex.logger.log(Level.INFO, "going to get doctor's name");
+ String doctorName = ui.getDoctorName();
+ if (!doctors.isExistingDoctor(doctorName)) {
+ throw new RexException("No such doctor!");
+ }
+
+ appointments.getAppointmentByIndex(index).bookPatient(patients.getPatientFromNric(nric));
+ appointments.getAppointmentByIndex(index).bookDoctor(doctors.getDoctorFromName(doctorName));
+ ui.showAppointmentBookedMessage(appointments.getAppointmentByIndex(index));
+
+ assert !appointments.isEmpty() : "No appointments!";
+ storage.saveAppointments(appointments);
+ } catch (NumberFormatException e) {
+ throw new RexException("Index error!");
+ }
+
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/EditPatientCommand.java b/src/main/java/seedu/rex/commands/EditPatientCommand.java
new file mode 100644
index 0000000000..dd6d95579b
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/EditPatientCommand.java
@@ -0,0 +1,55 @@
+package seedu.rex.commands;
+
+import seedu.rex.Rex;
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+import java.util.logging.Level;
+
+/**
+ * Edits a patient from the list of patients.
+ */
+public class EditPatientCommand extends Command {
+
+ public static final String COMMAND_WORD = "edit";
+ private final String trimmedCommand;
+
+ public EditPatientCommand(String trimmedCommand) {
+ this.trimmedCommand = trimmedCommand;
+ }
+
+ /**
+ * Edits an existing patient to the patient list using details inputted by the user.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object of the program.
+ * @param storage Storage object used for saving data to files.
+ * @throws RexException If there is an error in the NRIC inputted by the user, the data fails
+ * to save successfully, or the NRIC already exists in the patient list.
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage)
+ throws RexException {
+ assert patients != null : "patient ArrayList is null";
+ assert ui != null : "ui is null";
+ assert storage != null : "storage is null";
+ Rex.logger.log(Level.INFO, "going to extract NRIC");
+ String nric = extractNric(trimmedCommand, COMMAND_WORD);
+
+ if (!patients.isExistingPatient(nric)) {
+ throw new RexException("A patient with this NRIC has not been registered!");
+ }
+
+ int index = patients.editExistingPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth());
+ assert index > -1 : "Invalid index!";
+ ui.showLine();
+ ui.showPatientEdited(patients.getPatientUsingIndex(index));
+ storage.savePatients(patients);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/seedu/rex/commands/ExitCommand.java b/src/main/java/seedu/rex/commands/ExitCommand.java
new file mode 100644
index 0000000000..6bd2423b63
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/ExitCommand.java
@@ -0,0 +1,32 @@
+package seedu.rex.commands;
+
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+/**
+ * Exits program.
+ */
+public class ExitCommand extends Command {
+
+ public static final String COMMAND_WORD = "bye";
+ public static final String MESSAGE = "Bye. Hope to see you again soon!";
+
+ /**
+ * Says goodbye to user and exits Rex.
+ *
+ * @param patients PatientList object.
+ * @param doctors AppointmentList object.
+ * @param appointments DoctorList object.
+ * @param ui Ui object.
+ * @param storage Storage object.
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui,
+ Storage storage) {
+ isExit = true;
+ ui.showExit();
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/ListApptCommand.java b/src/main/java/seedu/rex/commands/ListApptCommand.java
new file mode 100644
index 0000000000..cc431e0ec3
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/ListApptCommand.java
@@ -0,0 +1,63 @@
+package seedu.rex.commands;
+
+import seedu.rex.Rex;
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Patient;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+import java.util.logging.Level;
+
+/**
+ * List appointments of patient.
+ */
+public class ListApptCommand extends Command {
+
+ public static final String COMMAND_WORD = "appointments";
+ private final String trimmedCommand;
+
+ public ListApptCommand(String trimmedCommand) {
+ this.trimmedCommand = trimmedCommand;
+ }
+
+ /**
+ * Lists appointments of a patient.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object.
+ * @param storage Storage object.
+ * @throws RexException If the input NRIC does not exist in system
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage)
+ throws RexException {
+ assert patients != null : "patient ArrayList is null";
+ assert ui != null : "ui is null";
+ assert storage != null : "storage is null";
+ Rex.logger.log(Level.INFO, "going to extract NRIC");
+ String nric = extractNric(trimmedCommand, COMMAND_WORD);
+
+ if (!patients.isExistingPatient(nric)) {
+ throw new RexException("A patient with this NRIC has not been registered!");
+ }
+ Patient targetPatient = patients.getPatientFromNric(nric);
+ assert targetPatient != null : "Null target patient!";
+ ui.showAppointmentsListHeader(nric);
+
+ int i;
+ for (i = 0; i < appointments.getSize(); i++) {
+ Patient tempPatient = appointments.getAppointmentByIndex(i).getPatient();
+ if (tempPatient != null && tempPatient.equals(targetPatient)) {
+ ui.showAppointmentLine(appointments.getAppointmentByIndex(i), i + 1);
+ }
+ }
+ if (i == 0) {
+ ui.showNoBookedAppointmentsMessage();
+ }
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/ListPatientCommand.java b/src/main/java/seedu/rex/commands/ListPatientCommand.java
new file mode 100644
index 0000000000..2ab2660288
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/ListPatientCommand.java
@@ -0,0 +1,31 @@
+package seedu.rex.commands;
+
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+/**
+ * Lists patients.
+ */
+public class ListPatientCommand extends Command {
+
+ public static final String COMMAND_WORD = "list";
+
+ /**
+ * List patients.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object.
+ * @param storage Storage object.
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui,
+ Storage storage) {
+
+ ui.listPatients(patients);
+ }
+}
diff --git a/src/main/java/seedu/rex/commands/RetrievePatientCommand.java b/src/main/java/seedu/rex/commands/RetrievePatientCommand.java
new file mode 100644
index 0000000000..f0ee8d5873
--- /dev/null
+++ b/src/main/java/seedu/rex/commands/RetrievePatientCommand.java
@@ -0,0 +1,53 @@
+package seedu.rex.commands;
+
+import seedu.rex.Rex;
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.storage.Storage;
+import seedu.rex.ui.Ui;
+
+import java.util.logging.Level;
+
+/**
+ * Retrieves patient details.
+ */
+public class RetrievePatientCommand extends Command {
+
+ public static final String COMMAND_WORD = "retrieve";
+ private final String trimmedCommand;
+
+ public RetrievePatientCommand(String trimmedCommand) {
+ this.trimmedCommand = trimmedCommand;
+ }
+
+ /**
+ * Retrieves patient from patient list using details inputted by the user.
+ *
+ * @param patients PatientList object.
+ * @param doctors DoctorList object.
+ * @param appointments AppointmentList object.
+ * @param ui Ui object.
+ * @param storage Storage object.
+ * @throws RexException If there is issue executing command.
+ */
+ @Override
+ public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage)
+ throws RexException {
+ assert patients != null : "patient ArrayList is null";
+ assert ui != null : "ui is null";
+ assert storage != null : "storage is null";
+ Rex.logger.log(Level.INFO, "going to extract NRIC");
+ String nric = extractNric(trimmedCommand, COMMAND_WORD);
+
+ int index = patients.getExistingPatient(nric);
+ assert index > -2 : "Unexpected index!";
+ if (index < 0) {
+ throw new RexException("No such patient!");
+ }
+ Rex.logger.log(Level.INFO, "going to show patients");
+ ui.showPatient(patients.getPatientUsingIndex(index));
+ Rex.logger.log(Level.INFO, "end of retrieve command");
+ }
+}
diff --git a/src/main/java/seedu/rex/data/AppointmentList.java b/src/main/java/seedu/rex/data/AppointmentList.java
new file mode 100644
index 0000000000..744ccf9f71
--- /dev/null
+++ b/src/main/java/seedu/rex/data/AppointmentList.java
@@ -0,0 +1,81 @@
+package seedu.rex.data;
+
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Appointment;
+
+import java.util.ArrayList;
+import java.util.stream.Collectors;
+
+/**
+ * Contains ArrayList of appointments.
+ */
+public class AppointmentList {
+ private final ArrayList appointments;
+
+ public AppointmentList() {
+ appointments = new ArrayList<>();
+ }
+
+ /**
+ * Initializes patients ArrayList using parameter.
+ *
+ * @param appointments Appointments list to use.
+ */
+ public AppointmentList(ArrayList appointments) {
+ this.appointments = appointments;
+ }
+
+ public ArrayList getAppointments() {
+ return appointments;
+ }
+
+
+ /**
+ * Returns if ArrayList is empty.
+ *
+ * @return True if empty, false if not.
+ */
+ public boolean isEmpty() {
+ return appointments.isEmpty();
+ }
+
+ /**
+ * Returns size of ArrayList.
+ *
+ * @return Size of ArrayList.
+ */
+ public int getSize() {
+ return appointments.size();
+ }
+
+ /**
+ * Returns appointment of given index.
+ *
+ * @param index Index of appointment.
+ * @return Appointment at that index.
+ */
+ public Appointment getAppointmentByIndex(int index) throws RexException {
+ if (index >= getSize()) {
+ throw new RexException("Invalid index!");
+ }
+ return appointments.get(index);
+ }
+
+ /**
+ * Adds appointment to the ArrayList.
+ *
+ * @param appointment Appointment to add.
+ */
+ public void addAppointment(Appointment appointment) {
+ appointments.add(appointment);
+ }
+
+ /**
+ * Returns ArrayList of available appointments.
+ *
+ * @return Appointments that are not booked.
+ */
+ public ArrayList getAvailableAppointments() {
+ return (ArrayList) appointments.stream().filter((a) -> !a.isBooked()).collect(Collectors.toList());
+ }
+}
diff --git a/src/main/java/seedu/rex/data/DoctorList.java b/src/main/java/seedu/rex/data/DoctorList.java
new file mode 100644
index 0000000000..b0086f5a30
--- /dev/null
+++ b/src/main/java/seedu/rex/data/DoctorList.java
@@ -0,0 +1,128 @@
+package seedu.rex.data;
+
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Doctor;
+
+import java.util.ArrayList;
+
+/**
+ * Contains ArrayList of doctors.
+ */
+public class DoctorList {
+
+ private final ArrayList doctors;
+
+ /**
+ * Initializes doctors ArrayList.
+ */
+ public DoctorList() {
+ doctors = new ArrayList<>();
+ }
+
+ /**
+ * Initializes doctors ArrayList using parameter.
+ *
+ * @param doctors Doctors list to use.
+ */
+ public DoctorList(ArrayList doctors) {
+ this.doctors = doctors;
+ }
+
+ /**
+ * Returns size of doctors.
+ *
+ * @return Length of doctors.
+ */
+ public int getSize() {
+ return doctors.size();
+ }
+
+ /**
+ * Returns doctor using index.
+ *
+ * @param index Index of doctor.
+ * @return doctor at that index.
+ */
+ public Doctor getDoctorUsingIndex(int index) {
+ return doctors.get(index);
+ }
+
+ /**
+ * Adds doctor to doctors ArrayList.
+ *
+ * @param doctor doctor to add.
+ */
+ public void addDoctor(Doctor doctor) {
+ doctors.add(doctor);
+ }
+
+ /**
+ * Returns list of doctors.
+ *
+ * @return List of doctors.
+ */
+ public ArrayList getDoctors() {
+ return doctors;
+ }
+
+ /**
+ * Checks if doctor exists.
+ *
+ * @param name Name of doctor.
+ * @return True if doctor already exist, false otherwise.
+ */
+ public boolean isExistingDoctor(String name) {
+ return getExistingDoctor(name) > -1;
+ }
+
+ /**
+ * Gets index of existing doctor.
+ *
+ * @param name Name of doctor.
+ * @return Index of doctor, -1 if doctor doesn't exist.
+ */
+ public int getExistingDoctor(String name) {
+ assert name != null && !name.equals("") : "Cannot get doctor of null name";
+
+ for (int i = 0; i < getSize(); i++) {
+ if (getDoctorUsingIndex(i).getName().equals(name)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Gets doctor using name.
+ *
+ * @param name Name of doctor.
+ * @return Doctor with that naem.
+ */
+ public Doctor getDoctorFromName(String name) {
+ for (Doctor doctor : doctors) {
+ if (doctor.getName().equals(name)) {
+ return doctor;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Deletes doctor with given name.
+ *
+ * @param doctorName Name of doctor.
+ * @return Removed doctor.
+ */
+ public Doctor deleteDoctor(String doctorName) throws RexException {
+ if (doctors.size() == 0) {
+ throw new RexException("No doctors!");
+ }
+ int i;
+ for (i = 0; i < getSize(); i++) {
+ if (getDoctorUsingIndex(i).getName().equals(doctorName)) {
+ return doctors.remove(i);
+ }
+ }
+ throw new RexException("Doctor not found!");
+ }
+}
diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java
new file mode 100644
index 0000000000..c5c2efcb6c
--- /dev/null
+++ b/src/main/java/seedu/rex/data/PatientList.java
@@ -0,0 +1,158 @@
+package seedu.rex.data;
+
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Patient;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+
+/**
+ * Contains ArrayList of patients.
+ */
+public class PatientList {
+
+ private final ArrayList patients;
+
+ /**
+ * Initializes patients ArrayList.
+ */
+ public PatientList() {
+ patients = new ArrayList<>();
+ }
+
+ /**
+ * Initializes patients ArrayList using parameter.
+ *
+ * @param patients Patients list to use.
+ */
+ public PatientList(ArrayList patients) {
+ this.patients = patients;
+ }
+
+ /**
+ * Returns size of patients.
+ *
+ * @return Length of patients.
+ */
+ public int getSize() {
+ return patients.size();
+ }
+
+ /**
+ * Returns patient using index.
+ *
+ * @param index Index of patient.
+ * @return patient at that index.
+ */
+ public Patient getPatientUsingIndex(int index) {
+ return patients.get(index);
+ }
+
+ /**
+ * Adds patient to patients ArrayList.
+ *
+ * @param patient patient to add.
+ */
+ public void addPatient(Patient patient) {
+ patients.add(patient);
+ }
+
+ /**
+ * Adds a new patient with given details to patients ArrayList.
+ *
+ * @param name Name of the patient.
+ * @param nric NRIC of the patient.
+ * @param dateOfBirth Patient's date of birth.
+ */
+ public void addNewPatient(String name, String nric, LocalDate dateOfBirth) {
+ addPatient(new Patient(name, nric, dateOfBirth));
+ }
+
+ /**
+ * Edits an existing patient with given details to patients ArrayList.
+ *
+ * @param name Name of the patient.
+ * @param nric NRIC of the patient.
+ * @param dateOfBirth Patient's date of birth.
+ */
+ public int editExistingPatient(String name, String nric, LocalDate dateOfBirth) {
+ int index = getExistingPatient(nric);
+ patients.remove(index);
+ Patient patient = (new Patient(name, nric, dateOfBirth));
+ patients.add(index, patient);
+ return index;
+ }
+
+
+ /**
+ * Checks if the NRIC entered by the user already exists in the patient list.
+ *
+ * @param nric The NRIC entered by the user.
+ * @return true if NRIC already exists; false otherwise.
+ */
+ public boolean isExistingPatient(String nric) {
+ return getExistingPatient(nric) > -1;
+ }
+
+ /**
+ * Finds NRIC entered by the user from the patient list.
+ * Returns -1 if not found.
+ *
+ * @param nric The NRIC entered by the user.
+ * @return index of the patient with the NRIC; -1 otherwise.
+ */
+ public int getExistingPatient(String nric) {
+ assert nric != null && !nric.equals("") : "Cannot get patient of null nric";
+
+ for (int i = 0; i < getSize(); i++) {
+ if (getPatientUsingIndex(i).getNric().equals(nric)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Gets patient using NRIC.
+ *
+ * @param nric NRIC of patient.
+ * @return patient with given NRIC.
+ */
+ public Patient getPatientFromNric(String nric) {
+ for (Patient patient : patients) {
+ if (patient.getNric().equals(nric)) {
+ return patient;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Deletes Patient with the NRIC entered by the user.
+ *
+ * @param nric NRIC entered by the user
+ * @return the deleted Patient Object
+ */
+ public Patient deletePatient(String nric) throws RexException {
+ if (patients.size() == 0) {
+ throw new RexException("No patients!");
+ }
+ int i;
+ for (i = 0; i < getSize(); i++) {
+ if (getPatientUsingIndex(i).getNric().equals(nric)) {
+ return patients.remove(i);
+ }
+ }
+ throw new RexException("Patient not found!");
+ }
+
+ /**
+ * Returns list of patients.
+ *
+ * @return Patients list.
+ */
+ public ArrayList getPatients() {
+ return patients;
+ }
+
+}
diff --git a/src/main/java/seedu/rex/data/exception/RexException.java b/src/main/java/seedu/rex/data/exception/RexException.java
new file mode 100644
index 0000000000..aecd982316
--- /dev/null
+++ b/src/main/java/seedu/rex/data/exception/RexException.java
@@ -0,0 +1,18 @@
+package seedu.rex.data.exception;
+
+/**
+ * Throws exceptions relating to Rex.
+ */
+public class RexException extends Exception {
+
+ private static final String OOPS = "☹ OOPS!!! ";
+
+ /**
+ * Initializes message to throw.
+ *
+ * @param message Exception message to show.
+ */
+ public RexException(String message) {
+ super(OOPS + message);
+ }
+}
diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java
new file mode 100644
index 0000000000..7ff36a4376
--- /dev/null
+++ b/src/main/java/seedu/rex/data/hospital/Appointment.java
@@ -0,0 +1,95 @@
+package seedu.rex.data.hospital;
+
+import java.time.LocalDate;
+
+/**
+ * Appointment class.
+ */
+public class Appointment {
+ private final LocalDate date;
+ private Patient patient;
+ private Doctor doctor;
+ private Boolean isBooked;
+
+ public Appointment(LocalDate date) {
+ this.date = date;
+ isBooked = false;
+ }
+
+ public LocalDate getDate() {
+ return date;
+ }
+
+ public Patient getPatient() {
+ return patient;
+ }
+
+ public void setPatient(Patient patient) {
+ this.patient = patient;
+ }
+
+ public Doctor getDoctor() {
+ return doctor;
+ }
+
+ public void setDoctor(Doctor doctor) {
+ this.doctor = doctor;
+ }
+
+ /**
+ * Checks if appointment is booked.
+ *
+ * @return If appointment is booked.
+ */
+ public Boolean isBooked() {
+ return isBooked;
+ }
+
+ /**
+ * Books an appointment for the patient.
+ *
+ * @param patient Patient to schedule appointment with.
+ */
+ public void bookPatient(Patient patient) {
+ this.patient = patient;
+ isBooked = true;
+ }
+
+ /**
+ * Removes booking.
+ */
+ public void removeBooking() {
+ this.patient = null;
+ this.doctor = null;
+ isBooked = false;
+ }
+
+ /**
+ * Formats appointment to a string.
+ *
+ * @return String formatted.
+ */
+ @Override
+ public String toString() {
+ String date = this.date.toString();
+
+ String bookedStatus = isBooked ? "booked" : "available";
+ String patientNric = patient == null ? null : patient.getNric();
+ String doctorName = doctor == null ? null : doctor.getName();
+
+ if (bookedStatus.contentEquals("booked")) {
+ return date + " | " + bookedStatus + " | " + patientNric + " | " + doctorName;
+ } else {
+ return date + " | " + bookedStatus;
+ }
+ }
+
+ /**
+ * Books doctor to appointment.
+ *
+ * @param doctor Doctor to book.
+ */
+ public void bookDoctor(Doctor doctor) {
+ this.doctor = doctor;
+ }
+}
diff --git a/src/main/java/seedu/rex/data/hospital/Doctor.java b/src/main/java/seedu/rex/data/hospital/Doctor.java
new file mode 100644
index 0000000000..0a4a269e0c
--- /dev/null
+++ b/src/main/java/seedu/rex/data/hospital/Doctor.java
@@ -0,0 +1,26 @@
+package seedu.rex.data.hospital;
+
+/**
+ * Doctor class.
+ */
+public class Doctor {
+ private final String name;
+
+ public Doctor(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns doctor's name.
+ *
+ * @return Doctor's name in String
+ */
+ @Override
+ public String toString() {
+ return name;
+ }
+}
diff --git a/src/main/java/seedu/rex/data/hospital/Patient.java b/src/main/java/seedu/rex/data/hospital/Patient.java
new file mode 100644
index 0000000000..7f5b53f2f1
--- /dev/null
+++ b/src/main/java/seedu/rex/data/hospital/Patient.java
@@ -0,0 +1,54 @@
+package seedu.rex.data.hospital;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Patient class.
+ */
+public class Patient {
+
+ private String name;
+ private String nric;
+ private LocalDate dateOfBirth;
+
+ public Patient(String name, String nric, LocalDate dateOfBirth) {
+ setName(name);
+ setNric(nric);
+ setDateOfBirth(dateOfBirth);
+ }
+
+ public LocalDate getDateOfBirth() {
+ return dateOfBirth;
+ }
+
+ public void setDateOfBirth(LocalDate dateOfBirth) {
+ this.dateOfBirth = dateOfBirth;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getNric() {
+ return nric;
+ }
+
+ public void setNric(String nric) {
+ this.nric = nric;
+ }
+
+ /**
+ * Returns the Patient object as a String for printing or writing to a file.
+ *
+ * @return Patient's details as a String in a particular format.
+ */
+ @Override
+ public String toString() {
+ return name + " | " + nric + " | " + dateOfBirth.format(DateTimeFormatter.ISO_DATE);
+ }
+}
diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java
new file mode 100644
index 0000000000..7d2731bf4a
--- /dev/null
+++ b/src/main/java/seedu/rex/parser/Parser.java
@@ -0,0 +1,155 @@
+package seedu.rex.parser;
+
+import seedu.rex.Rex;
+import seedu.rex.commands.AddDoctorCommand;
+import seedu.rex.commands.AddPatientCommand;
+import seedu.rex.commands.BookApptCommand;
+import seedu.rex.commands.Command;
+import seedu.rex.commands.CreateApptCommand;
+import seedu.rex.commands.DeleteApptCommand;
+import seedu.rex.commands.DeleteDoctorCommand;
+import seedu.rex.commands.DeletePatientCommand;
+import seedu.rex.commands.EditApptCommand;
+import seedu.rex.commands.EditPatientCommand;
+import seedu.rex.commands.ExitCommand;
+import seedu.rex.commands.ListApptCommand;
+import seedu.rex.commands.ListPatientCommand;
+import seedu.rex.commands.RetrievePatientCommand;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Appointment;
+import seedu.rex.data.hospital.Doctor;
+import seedu.rex.data.hospital.Patient;
+
+import java.time.LocalDate;
+
+/**
+ * Makes sense of user command.
+ */
+public class Parser {
+
+ /**
+ * Reads inputted patient details and returns the patient.
+ *
+ * @param line Input line to parse to patient details.
+ * @return Patient object with patient details.
+ */
+ public static Patient readPatient(String line) {
+ assert line != null && !line.equals("") : "No patients to read!";
+
+ String[] patientDetails = line.split(" \\| ");
+ String name = patientDetails[0];
+ String nric = patientDetails[1];
+ LocalDate dateOfBirth = LocalDate.parse(patientDetails[2]);
+ return new Patient(name, nric, dateOfBirth);
+ }
+
+ /**
+ * Reads in appointment and returns Appointment object.
+ *
+ * @param line Line to parse.
+ * @return Appointment object.
+ */
+ public static Appointment readAppointment(String line) {
+ String[] appointmentComponents = line.split(" \\| ");
+ LocalDate date = LocalDate.parse(appointmentComponents[0]);
+ String bookedStatus = appointmentComponents[1];
+ String nric;
+ String doctorName;
+ if (bookedStatus.contentEquals("booked")) {
+ nric = appointmentComponents[2];
+ doctorName = appointmentComponents[3];
+ } else {
+ nric = null;
+ doctorName = null;
+ }
+
+ Appointment appointment = new Appointment(date);
+ if (bookedStatus.equals("booked")) {
+ appointment.bookPatient(Rex.getPatients().getPatientFromNric(nric));
+ }
+ if (doctorName != null && !doctorName.equals("null")) {
+ appointment.setDoctor(Rex.getDoctors().getDoctorFromName(doctorName));
+ }
+ return appointment;
+ }
+
+ /**
+ * Reads and parse command.
+ *
+ * @param fullCommand Input string.
+ * @return Command to be ran.
+ * @throws RexException if command does not exist.
+ */
+ public static Command parse(String fullCommand) throws RexException {
+ assert fullCommand != null && !fullCommand.equals("") : "No command to parse!";
+
+ String trimmedCommand = fullCommand.trim().toLowerCase();
+ Command command;
+ String[] words = trimmedCommand.split(" ");
+ int length = 2;
+ switch (words[0]) {
+ case ExitCommand.COMMAND_WORD:
+ command = new ExitCommand();
+ length = 1;
+ break;
+ case AddPatientCommand.COMMAND_WORD:
+ command = new AddPatientCommand(trimmedCommand);
+ break;
+ case BookApptCommand.COMMAND_WORD:
+ command = new BookApptCommand(trimmedCommand);
+ break;
+ case CreateApptCommand.COMMAND_WORD:
+ command = new CreateApptCommand();
+ length = 1;
+ break;
+ case EditPatientCommand.COMMAND_WORD:
+ command = new EditPatientCommand(trimmedCommand);
+ break;
+ case DeletePatientCommand.COMMAND_WORD:
+ command = new DeletePatientCommand(trimmedCommand);
+ break;
+ case ListApptCommand.COMMAND_WORD:
+ command = new ListApptCommand(trimmedCommand);
+ break;
+ case ListPatientCommand.COMMAND_WORD:
+ command = new ListPatientCommand();
+ length = 1;
+ break;
+ case RetrievePatientCommand.COMMAND_WORD:
+ command = new RetrievePatientCommand(trimmedCommand);
+ break;
+ case AddDoctorCommand.COMMAND_WORD:
+ command = new AddDoctorCommand(trimmedCommand);
+ break;
+ case DeleteDoctorCommand.COMMAND_WORD:
+ command = new DeleteDoctorCommand(trimmedCommand);
+ break;
+ case EditApptCommand.COMMAND_WORD:
+ command = new EditApptCommand(trimmedCommand);
+ break;
+ case DeleteApptCommand.COMMAND_WORD:
+ command = new DeleteApptCommand(trimmedCommand);
+ break;
+ default:
+ throw new RexException(Command.COMMAND_ERROR);
+ }
+ if (!(command instanceof ExitCommand) && words.length < length) {
+ throw new RexException("Invalid input!");
+ }
+ return command;
+ }
+
+
+ /**
+ * Parses and reads doctor.
+ *
+ * @param line Line to parse.
+ * @return Doctor object.
+ */
+ public static Doctor readDoctor(String line) {
+ assert line != null && !line.equals("") : "No doctors to read!";
+
+ String name = line.trim();
+ return new Doctor(name);
+ }
+}
diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java
new file mode 100644
index 0000000000..9dd9e6229f
--- /dev/null
+++ b/src/main/java/seedu/rex/storage/Storage.java
@@ -0,0 +1,216 @@
+package seedu.rex.storage;
+
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.DoctorList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Appointment;
+import seedu.rex.data.hospital.Doctor;
+import seedu.rex.data.hospital.Patient;
+import seedu.rex.parser.Parser;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+
+/**
+ * Loads and saves data to file.
+ */
+public class Storage {
+ public static final String LOAD_ERROR = "Error loading file.";
+ private static final String READ_ERROR = "Error reading file.";
+ private static final String DIRECTORY_ERROR = "Error creating directory.";
+ private static final String WRITE_ERROR = "Error writing file.";
+ private static final String APPOINTMENTS_FILE = "appointments.txt";
+ private static final String PATIENTS_FILE = "patients.txt";
+ private static final String DOCTORS_FILE = "doctors.txt";
+ private final String folder;
+
+ /**
+ * Initializes path of folder and file.
+ *
+ * @param folderPath Full folder path.
+ */
+ public Storage(String folderPath) {
+ folder = folderPath;
+ }
+
+ /**
+ * Loads patients, stores them into ArrayList and returns the ArrayList.
+ *
+ * @return ArrayList of patients.
+ * @throws RexException If there is problem reading file.
+ */
+ public ArrayList loadPatients() throws RexException {
+ Path path = Paths.get(folder, PATIENTS_FILE);
+ ArrayList patients = new ArrayList<>();
+
+ if (Files.exists(path)) {
+ try {
+ BufferedReader bufferedReader = Files.newBufferedReader(path);
+
+ while (true) {
+ String line = bufferedReader.readLine();
+ if (line == null) {
+ break;
+ }
+
+ Patient patient = Parser.readPatient(line);
+ patients.add(patient);
+ }
+ } catch (IOException e) {
+ throw new RexException(READ_ERROR);
+ }
+ }
+
+ return patients;
+ }
+
+ /**
+ * Saves patients into file.
+ *
+ * @param patients ArrayList of patients to save.
+ * @throws RexException If there is problem writing or saving file.
+ */
+ public void savePatients(PatientList patients) throws RexException {
+ assert patients != null : "Saving null patients ArrayList";
+
+ StringBuilder patientsFileContent = new StringBuilder();
+
+ for (int i = 0; i < patients.getSize(); i++) {
+ // Need to format tasks
+ patientsFileContent.append(patients.getPatientUsingIndex(i));
+ patientsFileContent.append(System.lineSeparator());
+ }
+
+ writeToFile(patientsFileContent, PATIENTS_FILE);
+ }
+
+ /**
+ * Saves appointments into file.
+ *
+ * @param appointments ArrayList of appointments to save.
+ * @throws RexException If there is problem writing or saving file.
+ */
+ public void saveAppointments(AppointmentList appointments) throws RexException {
+ assert appointments != null : "Saving null appointments ArrayList";
+
+ StringBuilder appointmentsFileContent = new StringBuilder();
+
+ for (Appointment appointment : appointments.getAppointments()) {
+ appointmentsFileContent.append(appointment);
+ appointmentsFileContent.append(System.lineSeparator());
+ }
+
+ writeToFile(appointmentsFileContent, APPOINTMENTS_FILE);
+ }
+
+ /**
+ * Writes content to file.
+ *
+ * @param fileContent String content to write.
+ * @param file Filename to write to.
+ * @throws RexException If there is problem writing files.
+ */
+ private void writeToFile(StringBuilder fileContent, String file) throws RexException {
+ Path folderPath = Paths.get(folder);
+ if (!Files.exists(folderPath) && !new File(folder).mkdir()) {
+ throw new RexException(DIRECTORY_ERROR);
+ }
+
+ Path filePath = Paths.get(folder, file);
+ try {
+ BufferedWriter bufferedWriter = Files.newBufferedWriter(filePath);
+ bufferedWriter.write(fileContent.toString());
+ bufferedWriter.close();
+ } catch (IOException e) {
+ throw new RexException(WRITE_ERROR);
+ }
+ }
+
+ /**
+ * Loads appointments, stores them into ArrayList and returns the ArrayList.
+ *
+ * @return ArrayList of appointments.
+ * @throws RexException If there is problem reading file.
+ */
+ public ArrayList loadAppointments() throws RexException {
+ Path path = Paths.get(folder, APPOINTMENTS_FILE);
+ ArrayList appointments = new ArrayList<>();
+
+ if (Files.exists(path)) {
+ try {
+ BufferedReader bufferedReader = Files.newBufferedReader(path);
+
+ while (true) {
+ String line = bufferedReader.readLine();
+ if (line == null) {
+ break;
+ }
+
+ Appointment appointment = Parser.readAppointment(line);
+ appointments.add(appointment);
+ }
+ } catch (IOException e) {
+ throw new RexException(READ_ERROR);
+ }
+ }
+
+ return appointments;
+ }
+
+ /**
+ * Loads doctors, stores them into ArrayList and returns the ArrayList.
+ *
+ * @return ArrayList of doctors.
+ * @throws RexException If there is problem reading file.
+ */
+ public ArrayList loadDoctors() throws RexException {
+ Path path = Paths.get(folder, DOCTORS_FILE);
+ ArrayList doctors = new ArrayList<>();
+
+ if (Files.exists(path)) {
+ try {
+ BufferedReader bufferedReader = Files.newBufferedReader(path);
+
+ while (true) {
+ String line = bufferedReader.readLine();
+ if (line == null) {
+ break;
+ }
+
+ Doctor doctor = Parser.readDoctor(line);
+ doctors.add(doctor);
+ }
+ } catch (IOException e) {
+ throw new RexException(READ_ERROR);
+ }
+ }
+
+ return doctors;
+ }
+
+ /**
+ * Saves doctor to text file.
+ *
+ * @param doctors Doctors list.
+ * @throws RexException If there is error writing file.
+ */
+ public void saveDoctors(DoctorList doctors) throws RexException {
+ assert doctors != null : "Saving null doctors ArrayList";
+
+ StringBuilder doctorsFileContent = new StringBuilder();
+
+ for (int i = 0; i < doctors.getSize(); i++) {
+ doctorsFileContent.append(doctors.getDoctorUsingIndex(i));
+ doctorsFileContent.append(System.lineSeparator());
+ }
+
+ writeToFile(doctorsFileContent, DOCTORS_FILE);
+ }
+}
diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java
new file mode 100644
index 0000000000..31711ef911
--- /dev/null
+++ b/src/main/java/seedu/rex/ui/Ui.java
@@ -0,0 +1,430 @@
+package seedu.rex.ui;
+
+import seedu.rex.Rex;
+import seedu.rex.commands.Command;
+import seedu.rex.commands.ExitCommand;
+import seedu.rex.data.AppointmentList;
+import seedu.rex.data.PatientList;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Appointment;
+import seedu.rex.data.hospital.Doctor;
+import seedu.rex.data.hospital.Patient;
+import seedu.rex.storage.Storage;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Scanner;
+import java.util.logging.Level;
+
+/**
+ * Interacts with user.
+ */
+public class Ui {
+
+ public static final String LOGO = String.join(System.lineSeparator(),
+ " _ _ _ _ _ _____ __ __",
+ "| | | | (_| | | | | __ \\ \\ \\ / /",
+ "| |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \\ V / ",
+ "| __ |/ _ \\/ __| '_ \\| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \\ > < ",
+ "| | | | (_) \\__ | |_) | | || (_| | \\__ | (_| | |_| | | | |_| \\__ \\ | | \\ | __// . \\ ",
+ "|_| |_|\\___/|___| .__/|_|\\__\\__,_|_|___/\\__,_|\\__,_|_| \\__,_|___/ |_| \\_\\___/_/ \\_\\",
+ " | | ",
+ " |_| ");
+ private static final String DOTTED_LINE = "____________________________________________________________";
+ private static final String DATE_ERROR = "Error in date format.";
+ private static final String BLANK_INPUT_ERROR = "Input cannot be blank!";
+ private final Scanner in = new Scanner(System.in);
+
+ /**
+ * Prints string with indent.
+ *
+ * @param string String to print.
+ */
+ private void printWithIndent(String string) {
+ Arrays.stream(string.split(System.lineSeparator())).forEach((line) -> System.out.println("\t " + line));
+ }
+
+ /**
+ * Prints dotted line.
+ */
+ public void showLine() {
+ System.out.println("\t" + DOTTED_LINE);
+ }
+
+ /**
+ * Prints error message.
+ *
+ * @param message Error message to print.
+ */
+ public void showError(String message) {
+ printWithIndent(message);
+ }
+
+ /**
+ * Prints welcome message.
+ */
+ public void showWelcome() {
+ showLine();
+ printWithIndent(Command.MESSAGE);
+ showLine();
+ }
+
+ /**
+ * Prints loading error message.
+ */
+ public void showLoadingError() {
+ showError(Storage.LOAD_ERROR);
+ }
+
+ /**
+ * Prints exit message.
+ */
+ public void showExit() {
+ printWithIndent(ExitCommand.MESSAGE);
+ }
+
+ /**
+ * Prints date error message.
+ */
+ public void showDateInputError() {
+ showError(DATE_ERROR);
+ }
+
+ /**
+ * Prints a message to indicate successful addition of a patient.
+ *
+ * @param patient The newly added Patient.
+ */
+ public void showPatientAdded(Patient patient) {
+ printWithIndent("Patient successfully added: ");
+ printWithIndent(patient.toString());
+ }
+
+ /**
+ * Prints a message to indicate successful editting of a patient.
+ *
+ * @param patient The newly edited Patient.
+ */
+ public void showPatientEdited(Patient patient) {
+ printWithIndent("Patient successfully edited: ");
+ printWithIndent(patient.toString());
+ }
+
+ /**
+ * Prints a message to indicate successful deletion of a patient.
+ *
+ * @param patient The deleted Patient.
+ */
+ public void showPatientDeleted(Patient patient) {
+ printWithIndent("Patient successfully deleted: ");
+ printWithIndent(patient.toString());
+ }
+
+
+ /**
+ * Reads command from user.
+ *
+ * @return String command from user.
+ * @throws RexException If user input is blank.
+ */
+ public String readCommand() throws RexException {
+ String userInput;
+ printWithIndent("Enter command: ");
+ userInput = in.nextLine();
+ checkInputNotBlank(userInput);
+ return userInput;
+ }
+
+ /**
+ * Reads the name of a new patient from the user.
+ *
+ * @return The name of the patient to be added.
+ */
+ public String getPatientName() {
+ String patientName = "";
+ while (true) {
+ try {
+ printWithIndent("Enter patient name: ");
+ patientName = in.nextLine().trim();
+ checkInputNotBlank(patientName);
+ break;
+ } catch (RexException e) {
+ showLine();
+ showError(e.getMessage());
+ showLine();
+ }
+ }
+ return patientName;
+ }
+
+ /**
+ * Reads the date of birth of a new patient from the user.
+ *
+ * @return The date of birth of the patient.
+ */
+ public LocalDate getPatientDateOfBirth() {
+ while (true) {
+ try {
+ printWithIndent("Enter patient date of birth (YYYY-MM-DD) including the dashes: ");
+ return LocalDate.parse(in.nextLine().trim());
+ } catch (DateTimeParseException e) {
+ showLine();
+ showDateInputError();
+ showLine();
+ }
+ }
+ }
+
+ /**
+ * Shows patient details.
+ *
+ * @param patient Patient to show.
+ */
+ public void showPatient(Patient patient) {
+ assert patient != null : "Cannot show null patient!";
+
+ printWithIndent("Patient Details: ");
+ printWithIndent(patient.toString());
+ }
+
+ /**
+ * Prints patient not found message.
+ *
+ * @param nric NRIC inputted.
+ */
+ public void printPatientNotFound(String nric) {
+ printWithIndent("Patient " + nric + " not found in database!");
+ }
+
+ /**
+ * Gets appointment date from user.
+ *
+ * @return User input string.
+ */
+ public String getNewAppointmentDate() throws RexException {
+ printWithIndent("Please enter the date of appointment in YYYY-MM-DD.");
+ showLine();
+ String userInput = in.nextLine();
+ checkInputNotBlank(userInput);
+ return userInput;
+ }
+
+ /**
+ * Prints appointment creation message.
+ */
+ public void showAppointmentCreatedMessage() {
+ showLine();
+ printWithIndent("New appointment created!");
+ }
+
+ /**
+ * Gets appointment to be edited.
+ *
+ * @param appointments Arraylist of appointments.
+ * @return User input.
+ * @throws RexException If no appointments are available.
+ */
+ public String getAppointmentToEdit(AppointmentList appointments) throws RexException {
+ showLine();
+ printWithIndent("Here are the list of available appointments.");
+ int counter = 0;
+ for (Appointment appointment : appointments.getAvailableAppointments()) {
+ counter++;
+ printWithIndent(counter + ". " + appointment.getDate().toString());
+
+ }
+ if (counter == 0) {
+ throw new RexException("No appointments available!");
+ }
+ printWithIndent("Please enter the index of appointment to change to");
+ showLine();
+ String userInput = in.nextLine();
+ checkInputNotBlank(userInput);
+ return userInput;
+ }
+
+ /**
+ * Shows appointment booking message.
+ *
+ * @param appointment appointment that was booked.
+ */
+ public void showAppointmentBookedMessage(Appointment appointment) {
+ showLine();
+ printWithIndent("Appointment on " + appointment.getDate() + " booked!");
+
+ }
+
+ /**
+ * Prints patient's appointment list header.
+ *
+ * @param nric Patient's NRIC
+ */
+ public void showAppointmentsListHeader(String nric) {
+ printWithIndent("Listing appointments for patient " + nric + ": ");
+ }
+
+ /**
+ * Prints details of patient's appointment.
+ *
+ * @param appointment appointment to be printed
+ * @param counter appointment counter under patient
+ */
+ public void showAppointmentLine(Appointment appointment, int counter) {
+ printWithIndent(counter + ". " + appointment.getDate());
+ }
+
+ /**
+ * Prints message if patient has no booked appointments.
+ */
+ public void showNoBookedAppointmentsMessage() {
+ printWithIndent("No booked appointments found!");
+ }
+
+ /**
+ * Prints all patients.
+ *
+ * @param patients Patients to print.
+ */
+ public void listPatients(PatientList patients) {
+ printWithIndent("List of patients (" + patients.getPatients().size() + " in total):");
+ for (Patient patient : patients.getPatients()) {
+ printWithIndent("");
+ printWithIndent("Name: " + patient.getName());
+ printWithIndent("NRIC: " + patient.getNric());
+ printWithIndent("DOB: " + patient.getDateOfBirth());
+ }
+ }
+
+ /**
+ * Gets doctor name from user.
+ *
+ * @return Doctor's name.
+ */
+ public String getDoctorName() throws RexException {
+ printWithIndent("Enter doctor name: ");
+ String userInput = in.nextLine().toUpperCase().trim();
+ checkInputNotBlank(userInput);
+ return userInput;
+ }
+
+ /**
+ * Shows the doctor added.
+ *
+ * @param newDoctor Doctor added.
+ */
+ public void showDoctorAdded(Doctor newDoctor) {
+ printWithIndent("Doctor added: " + newDoctor.getName());
+ }
+
+ /**
+ * Shows deleted doctor.
+ *
+ * @param deletedDoctor Deleted doctor.
+ */
+ public void showDoctorDeleted(Doctor deletedDoctor) {
+ printWithIndent("Doctor successfully deleted: ");
+ printWithIndent(deletedDoctor.toString());
+ }
+
+ /**
+ * Shows doctor not found message.
+ *
+ * @param doctorName Name of doctor.
+ */
+ public void printDoctorNotFound(String doctorName) {
+ printWithIndent("Doctor " + doctorName + " not found in database!");
+ }
+
+ /**
+ * Displays only the Objects in ArrayList that is required to be shown.
+ *
+ * @param list Generic ArrayList
+ * @param Generic class
+ * @return Object in ArrayList
+ */
+ public int displayArrayList(ArrayList list) {
+ Rex.logger.log(Level.INFO, "display array list");
+ int i;
+ for (i = 0; i < list.size(); i++) {
+ printWithIndent((i + 1) + ". " + list.get(i));
+ }
+ return list.size();
+ }
+
+ /**
+ * Alerts user that there is a maximum allowable input.
+ *
+ * @param maxAllowableInput maximum allowable input
+ */
+ public void indexOutOfBoundsMessage(int maxAllowableInput) throws RexException {
+ throw new RexException("Index out of bounds! Input should be between 1 to " + maxAllowableInput + ".");
+ }
+
+ /**
+ * Gets object of Arraylist corresponding to user selection.
+ *
+ * @param list Generic ArrayList
+ * @param Generic class
+ * @return Object in ArrayList
+ */
+ public T getItemOfArrayList(ArrayList list) throws RexException {
+ int maxIndex = displayArrayList(list);
+ if (maxIndex < 1) {
+ throw new RexException("There are no available appointments to choose.");
+ }
+ printWithIndent("Enter the index: ");
+ String inputString = in.nextLine();
+ checkInputNotBlank(inputString);
+ int input = Integer.parseInt(inputString);
+ try {
+ return list.get(input - 1);
+ } catch (IndexOutOfBoundsException e) {
+ indexOutOfBoundsMessage(maxIndex);
+ return null;
+ }
+ }
+
+ /**
+ * Shows available appointments message.
+ */
+ public void showAvailableAppointmentsMessage() {
+ printWithIndent("Here are the list of available appointments: ");
+ }
+
+ /**
+ * Shows edit appointment message.
+ */
+ public void showEditAppointmentMessage() {
+ printWithIndent("Here are the appointments. Choose one to edit");
+ }
+
+ /**
+ * Shows deleted appointment.
+ *
+ * @param appointment Deleted appointment.
+ */
+ public void showDeleteAppointmentMessage(Appointment appointment) {
+ printWithIndent("Deleted appointment: " + appointment);
+ }
+
+ /**
+ * Shows delete appointment message.
+ */
+ public void showDeleteAppointmentMessage() {
+ printWithIndent("Choose appointment to delete: ");
+ }
+
+ /**
+ * Checks if a user's input is blank.
+ *
+ * @param userInput The user's input.
+ * @throws RexException If a user's input is blank.
+ */
+ public void checkInputNotBlank(String userInput) throws RexException {
+ if (userInput.isBlank()) {
+ throw new RexException(BLANK_INPUT_ERROR);
+ }
+ }
+}
diff --git a/src/test/java/seedu/duke/DukeTest.java b/src/test/java/seedu/duke/DukeTest.java
deleted file mode 100644
index 2dda5fd651..0000000000
--- a/src/test/java/seedu/duke/DukeTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package seedu.duke;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import org.junit.jupiter.api.Test;
-
-class DukeTest {
- @Test
- public void sampleTest() {
- assertTrue(true);
- }
-}
diff --git a/src/test/java/seedu/rex/commands/CommandTest.java b/src/test/java/seedu/rex/commands/CommandTest.java
new file mode 100644
index 0000000000..29bede3b2e
--- /dev/null
+++ b/src/test/java/seedu/rex/commands/CommandTest.java
@@ -0,0 +1,40 @@
+package seedu.rex.commands;
+
+import org.junit.jupiter.api.Test;
+import seedu.rex.data.exception.RexException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class CommandTest {
+
+ @Test
+ void isInteger_456456_returnsTrue() {
+ RetrievePatientCommand retrievePatientCommand = new RetrievePatientCommand("");
+ assertTrue(retrievePatientCommand.isInteger("456456"));
+ }
+
+ @Test
+ void isInteger_string_returnsFalse() {
+ RetrievePatientCommand retrievePatientCommand = new RetrievePatientCommand("");
+ assertFalse(retrievePatientCommand.isInteger("string"));
+ }
+
+ @Test
+ void extractNric_retrieveS9123456D_returnsS9123456DString() {
+ RetrievePatientCommand retrievePatientCommand = new RetrievePatientCommand("");
+ try {
+ assertEquals(retrievePatientCommand.extractNric("retrieve S9123456D", "retrieve"), "S9123456D");
+ } catch (RexException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ void extractNric_retrieveS91D_expectException() {
+ RetrievePatientCommand retrievePatientCommand = new RetrievePatientCommand("");
+ assertThrows(RexException.class, () -> retrievePatientCommand.extractNric("retrieve S91D", "retrieve"));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/seedu/rex/data/AppointmentListTest.java b/src/test/java/seedu/rex/data/AppointmentListTest.java
new file mode 100644
index 0000000000..adc35f719e
--- /dev/null
+++ b/src/test/java/seedu/rex/data/AppointmentListTest.java
@@ -0,0 +1,51 @@
+package seedu.rex.data;
+
+import org.junit.jupiter.api.Test;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Appointment;
+
+import java.time.LocalDate;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class AppointmentListTest {
+
+ @Test
+ void isEmpty_empty_true() {
+ AppointmentList appointmentList = new AppointmentList();
+ assertTrue(appointmentList.isEmpty());
+ }
+
+ @Test
+ void isEmpty_1Appointment_false() {
+ AppointmentList appointmentList = new AppointmentList();
+ appointmentList.addAppointment(new Appointment(LocalDate.now()));
+ assertFalse(appointmentList.isEmpty());
+ }
+
+ @Test
+ void getSize_1Appointment_1() {
+ AppointmentList appointmentList = new AppointmentList();
+ appointmentList.addAppointment(new Appointment(LocalDate.now()));
+ assertEquals(appointmentList.getSize(), 1);
+ }
+
+ @Test
+ void getAppointmentByIndex_sampleAppointment_sampleAppointment() throws RexException {
+ AppointmentList appointmentList = new AppointmentList();
+ Appointment appointment = new Appointment(LocalDate.now());
+ appointmentList.addAppointment(appointment);
+ assertEquals(appointmentList.getAppointmentByIndex(0), appointment);
+ }
+
+ @Test
+ void getAppointmentByIndex_invalidIndex_expectException() {
+ AppointmentList appointmentList = new AppointmentList();
+ Appointment appointment = new Appointment(LocalDate.now());
+ appointmentList.addAppointment(appointment);
+ assertThrows(RexException.class, () -> appointmentList.getAppointmentByIndex(1));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/seedu/rex/data/DoctorListTest.java b/src/test/java/seedu/rex/data/DoctorListTest.java
new file mode 100644
index 0000000000..3f75915b31
--- /dev/null
+++ b/src/test/java/seedu/rex/data/DoctorListTest.java
@@ -0,0 +1,15 @@
+package seedu.rex.data;
+
+import org.junit.jupiter.api.Test;
+import seedu.rex.data.exception.RexException;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class DoctorListTest {
+
+ @Test
+ void deleteDoctor_noDoctor_expectException() {
+ DoctorList doctorList = new DoctorList();
+ assertThrows(RexException.class, () -> doctorList.deleteDoctor(""));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/seedu/rex/data/PatientListTest.java b/src/test/java/seedu/rex/data/PatientListTest.java
new file mode 100644
index 0000000000..fe71255290
--- /dev/null
+++ b/src/test/java/seedu/rex/data/PatientListTest.java
@@ -0,0 +1,25 @@
+package seedu.rex.data;
+
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalDate;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+class PatientListTest {
+
+ @Test
+ void getSize_onePatient_1() {
+ PatientList patientList = new PatientList();
+ patientList.addNewPatient("test", "S9911444D", LocalDate.now());
+ assertEquals(patientList.getSize(), 1);
+ }
+
+ @Test
+ void getPatientFromNric_invalidNric_null() {
+ PatientList patientList = new PatientList();
+ patientList.addNewPatient("test", "S9911444D", LocalDate.now());
+ assertNull(patientList.getPatientFromNric("a"));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/seedu/rex/data/hospital/AppointmentTest.java b/src/test/java/seedu/rex/data/hospital/AppointmentTest.java
new file mode 100644
index 0000000000..fc87ef4523
--- /dev/null
+++ b/src/test/java/seedu/rex/data/hospital/AppointmentTest.java
@@ -0,0 +1,106 @@
+package seedu.rex.data.hospital;
+
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalDate;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class AppointmentTest {
+
+ @Test
+ void getDate_todayDate_todayDate() {
+ Appointment appointment = new Appointment(LocalDate.now());
+ assertEquals(LocalDate.now(), appointment.getDate());
+ }
+
+ @Test
+ void getPatient_samplePatient_samplePatient() {
+ Appointment appointment = new Appointment(LocalDate.now());
+ Patient patient = new Patient(null, null, null);
+ appointment.setPatient(patient);
+ assertEquals(patient, appointment.getPatient());
+ }
+
+ @Test
+ void setPatient_samplePatient_samplePatient() {
+ Appointment appointment = new Appointment(LocalDate.now());
+ Patient patient = new Patient(null, null, null);
+ appointment.setPatient(patient);
+ assertEquals(patient, appointment.getPatient());
+ }
+
+ @Test
+ void getDoctor_sampleDoctor_sampleDoctor() {
+ Appointment appointment = new Appointment(LocalDate.now());
+ Doctor doctor = new Doctor("hi");
+ appointment.setDoctor(doctor);
+ assertEquals(doctor, appointment.getDoctor());
+ }
+
+ @Test
+ void setDoctor_sampleDoctor_sampleDoctor() {
+ Appointment appointment = new Appointment(LocalDate.now());
+ Doctor doctor = new Doctor("hi");
+ appointment.setDoctor(doctor);
+ assertEquals(doctor, appointment.getDoctor());
+ }
+
+ @Test
+ void isBooked_booked_true() {
+ Appointment appointment = new Appointment(LocalDate.now());
+ appointment.bookPatient(new Patient(null, null, null));
+ assertTrue(appointment.isBooked());
+ }
+
+ @Test
+ void isBooked_notBooked_false() {
+ Appointment appointment = new Appointment(LocalDate.now());
+ assertFalse(appointment.isBooked());
+ }
+
+ @Test
+ void bookPatient_samplePatient_isBookedTrueAndSamplePatient() {
+ Appointment appointment = new Appointment(LocalDate.now());
+ Patient patient = new Patient(null, null, null);
+ appointment.bookPatient(patient);
+ assertEquals(patient, appointment.getPatient());
+ assertTrue(appointment.isBooked());
+ }
+
+ @Test
+ void removeBooking_removed_nullPatientAndIsBookedFalse() {
+ Appointment appointment = new Appointment(LocalDate.now());
+ Patient patient = new Patient(null, null, null);
+ appointment.bookPatient(patient);
+ appointment.removeBooking();
+ assertFalse(appointment.isBooked());
+ assertNull(appointment.getPatient());
+ assertNull(appointment.getDoctor());
+ }
+
+ @Test
+ void testToString_bookedAppointment_correctString() {
+ Appointment appointment = new Appointment(LocalDate.now());
+ Patient patient = new Patient(null, null, null);
+ appointment.bookPatient(patient);
+ assertEquals(LocalDate.now() + " | booked | null | null", appointment.toString());
+ }
+
+ @Test
+ void testToString_notBookedAppointment_correctString() {
+ Appointment appointment = new Appointment(LocalDate.now());
+ assertEquals(LocalDate.now() + " | available", appointment.toString());
+ }
+
+ @Test
+ void bookDoctor_sampleDoctor_sampleDoctor() {
+ Appointment appointment = new Appointment(LocalDate.now());
+ Doctor doctor = new Doctor("test");
+ appointment.bookDoctor(doctor);
+ assertEquals(doctor, appointment.getDoctor());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/seedu/rex/data/hospital/DoctorTest.java b/src/test/java/seedu/rex/data/hospital/DoctorTest.java
new file mode 100644
index 0000000000..8b7b99815e
--- /dev/null
+++ b/src/test/java/seedu/rex/data/hospital/DoctorTest.java
@@ -0,0 +1,20 @@
+package seedu.rex.data.hospital;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class DoctorTest {
+
+ @Test
+ void getName_sam_sam() {
+ Doctor sam = new Doctor("Sam");
+ assertEquals("Sam", sam.getName());
+ }
+
+ @Test
+ void testToString_sam_sam() {
+ Doctor sam = new Doctor("Sam");
+ assertEquals("Sam", sam.toString());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/seedu/rex/data/hospital/PatientTest.java b/src/test/java/seedu/rex/data/hospital/PatientTest.java
new file mode 100644
index 0000000000..ceead06597
--- /dev/null
+++ b/src/test/java/seedu/rex/data/hospital/PatientTest.java
@@ -0,0 +1,55 @@
+package seedu.rex.data.hospital;
+
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalDate;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class PatientTest {
+
+ @Test
+ void getDateOfBirth_todayDate_todayDate() {
+ Patient patient = new Patient("a", "b", LocalDate.now());
+ assertEquals(LocalDate.now(), patient.getDateOfBirth());
+ }
+
+ @Test
+ void setDateOfBirth_todayDate_todayDate() {
+ Patient patient = new Patient("a", "b", LocalDate.MIN);
+ patient.setDateOfBirth(LocalDate.now());
+ assertEquals(LocalDate.now(), patient.getDateOfBirth());
+ }
+
+ @Test
+ void getName_a_a() {
+ Patient patient = new Patient("a", "b", LocalDate.MIN);
+ assertEquals("a", patient.getName());
+ }
+
+ @Test
+ void setName_a_a() {
+ Patient patient = new Patient("z", "b", LocalDate.MIN);
+ patient.setName("a");
+ assertEquals("a", patient.getName());
+ }
+
+ @Test
+ void getNric_b_b() {
+ Patient patient = new Patient("z", "b", LocalDate.MIN);
+ assertEquals("b", patient.getNric());
+ }
+
+ @Test
+ void setNric_z_z() {
+ Patient patient = new Patient("z", "b", LocalDate.MIN);
+ patient.setNric("z");
+ assertEquals("z", patient.getNric());
+ }
+
+ @Test
+ void testToString_zbTodayDate_zbTodayDate() {
+ Patient patient = new Patient("z", "b", LocalDate.now());
+ assertEquals("z | b | " + LocalDate.now(), patient.toString());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/seedu/rex/parser/ParserTest.java b/src/test/java/seedu/rex/parser/ParserTest.java
new file mode 100644
index 0000000000..68ba5d500d
--- /dev/null
+++ b/src/test/java/seedu/rex/parser/ParserTest.java
@@ -0,0 +1,28 @@
+package seedu.rex.parser;
+
+import org.junit.jupiter.api.Test;
+import seedu.rex.commands.ExitCommand;
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Doctor;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ParserTest {
+ @Test
+ void parse_bye_returnsExitCommand() throws RexException {
+ assertTrue(Parser.parse("bye") instanceof ExitCommand);
+ }
+
+ @Test
+ void parse_invalidInput_expectException() {
+ assertThrows(RexException.class, () -> Parser.parse("exit"));
+ }
+
+ @Test
+ void readDoctor_doctorTan_returnsDoctorTan() {
+ Doctor doctor = new Doctor("Tan");
+ assertEquals(Parser.readDoctor("Tan").getName(), doctor.getName());
+ }
+}
diff --git a/src/test/java/seedu/rex/storage/StorageTest.java b/src/test/java/seedu/rex/storage/StorageTest.java
new file mode 100644
index 0000000000..12c39097f5
--- /dev/null
+++ b/src/test/java/seedu/rex/storage/StorageTest.java
@@ -0,0 +1,34 @@
+package seedu.rex.storage;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import seedu.rex.data.exception.RexException;
+import seedu.rex.data.hospital.Appointment;
+import seedu.rex.data.hospital.Doctor;
+import seedu.rex.data.hospital.Patient;
+
+import java.util.ArrayList;
+
+public class StorageTest {
+
+ @Test
+ public void loadAppointments_newFilePath_success() throws RexException {
+ ArrayList appointments = new ArrayList<>();
+ assertEquals(appointments, new Storage("test_data").loadAppointments());
+ }
+
+ @Test
+ public void loadPatients_newFilePath_success() throws RexException {
+ ArrayList patients = new ArrayList<>();
+ assertEquals(patients, new Storage("test_data").loadPatients());
+ }
+
+ @Test
+ public void loadDoctors_newFilePath_success() throws RexException {
+ ArrayList doctors = new ArrayList<>();
+ assertEquals(doctors, new Storage("test_data").loadDoctors());
+ }
+
+}
diff --git a/src/test/java/seedu/rex/ui/UiTest.java b/src/test/java/seedu/rex/ui/UiTest.java
new file mode 100644
index 0000000000..fdd4192bbc
--- /dev/null
+++ b/src/test/java/seedu/rex/ui/UiTest.java
@@ -0,0 +1,36 @@
+package seedu.rex.ui;
+
+import org.junit.jupiter.api.Test;
+import seedu.rex.data.exception.RexException;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class UiTest {
+
+ @Test
+ void readCommand_hello_returnsHelloString() throws RexException {
+
+ String input = "hello";
+ InputStream in = new ByteArrayInputStream(input.getBytes());
+ System.setIn(in);
+
+ assertEquals("hello", new Ui().readCommand());
+ }
+
+ @Test
+ void checkInputNotBlank_blankInput_expectException() {
+
+ assertThrows(RexException.class, () -> new Ui().checkInputNotBlank(""));
+ }
+
+ @Test
+ void checkInputNotBlank_string_expectNoException() {
+
+ assertDoesNotThrow(() -> new Ui().checkInputNotBlank("a"));
+ }
+}
\ No newline at end of file
diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT
index 892cb6cae7..a9f74f6341 100644
--- a/text-ui-test/EXPECTED.TXT
+++ b/text-ui-test/EXPECTED.TXT
@@ -1,9 +1,180 @@
-Hello from
- ____ _
-| _ \ _ _| | _____
-| | | | | | | |/ / _ \
-| |_| | |_| | < __/
-|____/ \__,_|_|\_\___|
-
-What is your name?
-Hello James Gosling
+ ____________________________________________________________
+ _ _ _ _ _ _____ __ __
+ | | | | (_| | | | | __ \ \ \ / /
+ | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \ V /
+ | __ |/ _ \/ __| '_ \| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \ > <
+ | | | | (_) \__ | |_) | | || (_| | \__ | (_| | |_| | | | |_| \__ \ | | \ | __// . \
+ |_| |_|\___/|___| .__/|_|\__\__,_|_|___/\__,_|\__,_|_| \__,_|___/ |_| \_\___/_/ \_\
+ | |
+ |_|
+ How may i assist you?
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ ☹ OOPS!!! I'm sorry, but I don't know what that means :-(
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ ☹ OOPS!!! Invalid input!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ ☹ OOPS!!! Invalid NRIC length!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ ☹ OOPS!!! Beginning character of NRIC must be 'S', 'T', 'F', or 'G'!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ ☹ OOPS!!! Number sequence of NRIC is invalid!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ ☹ OOPS!!! Number sequence of NRIC is invalid!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Enter patient name:
+ Enter patient date of birth (YYYY-MM-DD) including the dashes:
+ ____________________________________________________________
+ Error in date format.
+ ____________________________________________________________
+ Enter patient date of birth (YYYY-MM-DD) including the dashes:
+ ____________________________________________________________
+ Patient successfully added:
+ Trump | S9123456Z | 1960-06-14
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ ☹ OOPS!!! No such patient!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Patient Details:
+ Trump | S9123456Z | 1960-06-14
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ ☹ OOPS!!! A patient with this NRIC has not been registered!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Enter patient name:
+ Enter patient date of birth (YYYY-MM-DD) including the dashes:
+ ____________________________________________________________
+ Patient successfully edited:
+ Donald | S9123456Z | 1962-06-14
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Enter patient name:
+ Enter patient date of birth (YYYY-MM-DD) including the dashes:
+ ____________________________________________________________
+ Patient successfully added:
+ John | S9993222A | 1985-06-14
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Patient S9992222A not found in database!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Patient successfully deleted:
+ John | S9993222A | 1985-06-14
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ ☹ OOPS!!! No appointment sessions!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Please enter the date of appointment in YYYY-MM-DD.
+ ____________________________________________________________
+ Error in date format.
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Please enter the date of appointment in YYYY-MM-DD.
+ ____________________________________________________________
+ ____________________________________________________________
+ New appointment created!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Doctor added: TAN
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Enter doctor name:
+ ☹ OOPS!!! No such doctor!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Enter doctor name:
+ Here are the list of available appointments:
+ 1. 2020-10-10 | available
+ Enter the index:
+ ☹ OOPS!!! Index out of bounds! Input should be between 1 to 1.
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Enter doctor name:
+ Here are the list of available appointments:
+ 1. 2020-10-10 | available
+ Enter the index:
+ ____________________________________________________________
+ Appointment on 2020-10-10 booked!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Listing appointments for patient S9123456Z:
+ 1. 2020-10-10
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Please enter the date of appointment in YYYY-MM-DD.
+ ____________________________________________________________
+ ____________________________________________________________
+ New appointment created!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Here are the appointments. Choose one to edit
+ 1. 2020-10-10 | booked | S9123456Z | TAN
+ Enter the index:
+ Deleted appointment: 2020-10-10 | booked | S9123456Z | TAN
+ ____________________________________________________________
+ Here are the list of available appointments.
+ 1. 2020-10-10
+ 2. 2020-12-12
+ Please enter the index of appointment to change to
+ ____________________________________________________________
+ Enter doctor name:
+ ____________________________________________________________
+ Appointment on 2020-10-10 booked!
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Choose appointment to delete:
+ 1. 2020-10-10 | booked | S9123456Z | TAN
+ Enter the index:
+ Deleted appointment: 2020-10-10 | booked | S9123456Z | TAN
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Doctor successfully deleted:
+ TAN
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ List of patients (1 in total):
+
+ Name: Donald
+ NRIC: S9123456Z
+ DOB: 1962-06-14
+ ____________________________________________________________
+ Enter command:
+ ____________________________________________________________
+ Bye. Hope to see you again soon!
+ ____________________________________________________________
diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt
index f6ec2e9f95..9d92207070 100644
--- a/text-ui-test/input.txt
+++ b/text-ui-test/input.txt
@@ -1 +1,47 @@
-James Gosling
\ No newline at end of file
+James Gosling
+add
+add S9Z
+add B1234422B
+add S123B422Z
+add S123B4222
+add S9123456Z
+Trump
+06-06-1960
+1960-06-14
+retrieve S9993222A
+retrieve S9123456Z
+edit S9992222A
+edit S9123456Z
+Donald
+1962-06-14
+add S9993222A
+John
+1985-06-14
+delete S9992222A
+delete S9993222A
+book S9123456Z
+create
+2020-10-40
+create
+2020-10-10
+doctor tan
+book S9123456Z
+t
+book S9123456Z
+tan
+0
+book S9123456Z
+tan
+1
+appointments S9123456Z
+create
+2020-12-12
+editappt S9123456Z
+1
+1
+tan
+deleteappt S9123456Z
+1
+nodoctor tan
+list
+bye
\ No newline at end of file