diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 811b15aa0ce..e66fb808bc2 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -41,37 +41,74 @@ Here are some descriptions of the words we use throughout the User Guide: ![Ui1](images/Ui1.png) -## Lead features - -### Add lead [Coming soon] +### Add lead - What it does: Add potential leads and their basic information, e.g. name, age, year of study, major, etc. -- Command format: `add --name --age --year --major `. -- Example usage: `add --name Dave --age 22 --year 2 --major Psychology`. +- Command format: `addlead n/NAME p/PHONE e/EMAIL a/ADDRESS [t/TAG]...`. +- Example usage: `Example: addlead n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/classmate`. +- Acceptable values for each parameter: + - `NAME`: can contain any character. + - `PHONE`: any valid 8-digit integer. + - `EMAIL`: a string of the format `local-part@domain` + - `ADDRESS`: can contain any character. + - `TAG`: can contain any character. +- Precise expected outputs when the command succeeds: + +
+ +

After using addlead command

+
+ +- Precise expected outputs when the command fails: + +``` +Invalid command format! +addlead: Adds a lead to the address book. Parameters: n/NAME p/PHONE e/EMAIL a/ADDRESS [t/TAG]... +Example: addlead n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/classmate +``` + +### Add Client +- What it does: Add potential clients and their basic information, e.g. name, age, year of study, major, etc. +- Command format: `addclient n/NAME p/PHONE e/EMAIL a/ADDRESS [t/TAG]...`. +- Example usage: `Example: addclient n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/classmate`. - Acceptable values for each parameter: - - `name`: can contain any character, up to 100 characters long. - - `age`: any integer between `1` and `100` inclusive. - - `year`: any integer between `1` and `5` inclusive. - - `major`: can contain any character, up to 50 characters long. + - `NAME`: can contain any character. + - `PHONE`: any valid 8-digit integer. + - `EMAIL`: a string of the format `local-part@domain` + - `ADDRESS`: can contain any character. + - `TAG`: can contain any character. - Precise expected outputs when the command succeeds: -`Lead added. ` +
+ +

After using addclient command

+
- Precise expected outputs when the command fails: -`Lead failed to add. Please enter a valid command` +``` +Invalid command format! +addclient: Adds a client to the address book. Parameters: n/NAME p/PHONE e/EMAIL a/ADDRESS [t/TAG]... +Example: addclient n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/classmate +``` ### View all clients -- What it does: View all clients you have stored, including their basic information and index in the list of leads, e.g. id, name, age, gender, occupation, etc. +- What it does: View all clients you have stored, including their basic information and index in the list of clients, e.g. id, name, age, gender, occupation, etc. - Command: `listclient`. - Precise expected outputs when the command succeeds: +In output section of the `List of all clients` -- Precise expected outputs when the command fails: +

Examples of usage:

-`Failed to view all clients. Please enter a valid command` +
+ +

List of leads and clients

+ +

After using listclient command

+
### View all leads @@ -81,16 +118,22 @@ Here are some descriptions of the words we use throughout the User Guide: `List of all leads` -- Precise expected outputs when the command fails: +

Example usage:

+ +
+ +

List of leads and clients

+ +

After using listlead command

+
-`Failed to view all leads. Please enter a valid command` -### Delete lead [Coming soon] +### Delete [Coming soon] - What it does: Deletes a lead from your list of leads. -- Command format: `delete --id `. -- Example usage: `delete --id 1`. -- Acceptable values for `id` parameter: +- Command format: `delete INDEX`. +- Example usage: `delete 1`. +- Acceptable values for `INDEX` parameter: - Must be an integer from `1` to the last index of the leads list - Precise expected outputs when the command succeeds: @@ -98,19 +141,23 @@ Here are some descriptions of the words we use throughout the User Guide: - Precise expected outputs when the command fails: -`Lead failed to delete. Please enter a valid lead id` +``` +Invalid command format! +delete: Deletes the person identified by the index number used in the displayed person list. +Parameters: INDEX (must be a positive integer) +``` -### Add meeting time for lead [Coming soon] +### Add meeting time [Coming soon] - What it does: Adds a meeting time for a lead -- Command format: `addmeeting --lead --dt ` -- Example usage: `addmeeting --lead 1 --dt 23/9/2023 5:30PM` +- Command format: `addmeetingtime INDEX m/MEETING_TIME` +- Example usage: `addmeetingtime 1 m/12/12/2020 12:00` - Acceptable values for each parameter: - - `lead`: Any integer from `1` to the last index of the leads list - - `dt`: A valid DateTime String with the format dd/M/yyyy hh:mma. + - `INDEX`: Any integer from `1` to the last index of the leads list. + - `MEETING_TIME`: A string of format `dd/MM/yyyy HH:mm`. - Precise expected outputs when the command succeeds: -`Meeting time added to : ` +`Meeting time added to : ` - Precise expected outputs when the command fails: diff --git a/docs/images/List.png b/docs/images/List.png new file mode 100644 index 00000000000..11630bf8433 Binary files /dev/null and b/docs/images/List.png differ diff --git a/docs/images/Listclient.png b/docs/images/Listclient.png new file mode 100644 index 00000000000..97290b39b29 Binary files /dev/null and b/docs/images/Listclient.png differ diff --git a/docs/images/Listlead.png b/docs/images/Listlead.png new file mode 100644 index 00000000000..bf2e14200b5 Binary files /dev/null and b/docs/images/Listlead.png differ diff --git a/docs/images/addclient.png b/docs/images/addclient.png new file mode 100644 index 00000000000..331ee029d2f Binary files /dev/null and b/docs/images/addclient.png differ diff --git a/docs/images/addlead.png b/docs/images/addlead.png new file mode 100644 index 00000000000..ec3d7801561 Binary files /dev/null and b/docs/images/addlead.png differ diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/address/logic/commands/CommandResult.java index 249b6072d0d..984905acf57 100644 --- a/src/main/java/seedu/address/logic/commands/CommandResult.java +++ b/src/main/java/seedu/address/logic/commands/CommandResult.java @@ -19,13 +19,16 @@ public class CommandResult { /** The application should exit. */ private final boolean exit; + private String state; + /** * Constructs a {@code CommandResult} with the specified fields. */ - public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) { + public CommandResult(String feedbackToUser, boolean showHelp, boolean exit, String state) { this.feedbackToUser = requireNonNull(feedbackToUser); this.showHelp = showHelp; this.exit = exit; + this.state = state; } /** @@ -33,7 +36,7 @@ public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) { * and other fields set to their default value. */ public CommandResult(String feedbackToUser) { - this(feedbackToUser, false, false); + this(feedbackToUser, false, false, "null"); } public String getFeedbackToUser() { @@ -48,6 +51,10 @@ public boolean isExit() { return exit; } + public String checkState() { + return state; + } + @Override public boolean equals(Object other) { if (other == this) { diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/address/logic/commands/ExitCommand.java index 3dd85a8ba90..a1eb8126c9d 100644 --- a/src/main/java/seedu/address/logic/commands/ExitCommand.java +++ b/src/main/java/seedu/address/logic/commands/ExitCommand.java @@ -13,7 +13,7 @@ public class ExitCommand extends Command { @Override public CommandResult execute(Model model) { - return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true); + return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true, "exit"); } } diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/address/logic/commands/HelpCommand.java index bf824f91bd0..b33639d6e34 100644 --- a/src/main/java/seedu/address/logic/commands/HelpCommand.java +++ b/src/main/java/seedu/address/logic/commands/HelpCommand.java @@ -16,6 +16,6 @@ public class HelpCommand extends Command { @Override public CommandResult execute(Model model) { - return new CommandResult(SHOWING_HELP_MESSAGE, true, false); + return new CommandResult(SHOWING_HELP_MESSAGE, true, false, "help"); } } diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java index 84be6ad2596..aa067bfdb54 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/seedu/address/logic/commands/ListCommand.java @@ -13,8 +13,6 @@ public class ListCommand extends Command { public static final String COMMAND_WORD = "list"; public static final String MESSAGE_SUCCESS = "Listed all persons"; - - @Override public CommandResult execute(Model model) { requireNonNull(model); diff --git a/src/main/java/seedu/address/logic/commands/ViewCommand.java b/src/main/java/seedu/address/logic/commands/ViewCommand.java new file mode 100644 index 00000000000..d50fb94fbfa --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/ViewCommand.java @@ -0,0 +1,70 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import java.util.logging.Logger; + +import seedu.address.commons.core.LogsCenter; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.Messages; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.person.Person; + +/** + * Views specified person based on input index. + */ +public class ViewCommand extends Command { + + public static final String COMMAND_WORD = "view"; + + public static final String MESSAGE_SUCCESS = "Viewed Person Successfully"; + private static final String state = "view"; + + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Views the person identified by the index number used.\n" + + "Parameters: INDEX (must be a positive integer)\n" + + "Example: " + COMMAND_WORD + " 1"; + + private static final Logger logger = LogsCenter.getLogger(ViewCommand.class); + + private final Index targetIndex; + + public ViewCommand(Index targetIndex) { + this.targetIndex = targetIndex; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + + + if (targetIndex.getZeroBased() < 0 || targetIndex.getZeroBased() >= model.getFilteredPersonList().size()) { + logger.info(targetIndex.getZeroBased() + "+ " + model.getFilteredPersonList().size()); + throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + Person personToView = model.getFilteredPersonList().get(targetIndex.getZeroBased()); + model.view(personToView); + + logger.info("Target Index: " + targetIndex.getZeroBased()); + logger.info("Client to View: " + personToView); + return new CommandResult(MESSAGE_SUCCESS, false, false, "view"); + } + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (other == null || getClass() != other.getClass()) { + return false; + } + + ViewCommand that = (ViewCommand) other; + + return targetIndex.equals(that.targetIndex); + } +} + diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 9c1b67a72a6..1a7fa05374c 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -22,6 +22,7 @@ import seedu.address.logic.commands.ListClientCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.commands.ListLeadCommand; +import seedu.address.logic.commands.ViewCommand; import seedu.address.logic.parser.exceptions.ParseException; /** @@ -90,13 +91,16 @@ public Command parseCommand(String userInput) throws ParseException { case ListLeadCommand.COMMAND_WORD: return new ListLeadCommand(); - + case ConvertLeadToClientCommand.COMMAND_WORD: return new ConvertLeadToClientCommandParser().parse(arguments); case ConvertClientToLeadCommand.COMMAND_WORD: return new ConvertClientToLeadCommandParser().parse(arguments); + case ViewCommand.COMMAND_WORD: + return new ViewCommandParser().parse(arguments); + default: logger.finer("This user input caused a ParseException: " + userInput); throw new ParseException(MESSAGE_UNKNOWN_COMMAND); diff --git a/src/main/java/seedu/address/logic/parser/ViewCommandParser.java b/src/main/java/seedu/address/logic/parser/ViewCommandParser.java new file mode 100644 index 00000000000..6dfe9e6aa49 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/ViewCommandParser.java @@ -0,0 +1,29 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.ViewCommand; +import seedu.address.logic.parser.exceptions.ParseException; + +/** + * Parses input arguments and creates a new ViewCommand object + */ +public class ViewCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the ViewCommand + * and returns a ViewCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public ViewCommand parse(String args) throws ParseException { + try { + Index index = ParserUtil.parseIndex(args); + return new ViewCommand(index); + } catch (ParseException pe) { + throw new ParseException( + String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewCommand.MESSAGE_USAGE), pe); + } + } + +} diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index e43f4aec194..3c755b67924 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -140,7 +140,6 @@ public boolean equals(Object other) { AddressBook otherAddressBook = (AddressBook) other; return persons.equals(otherAddressBook.persons); } - @Override public int hashCode() { return persons.hashCode(); diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index 983601c8882..e97daf91eb9 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -13,7 +13,9 @@ * The API of the Model component. */ public interface Model { - /** {@code Predicate} that always evaluate to true */ + /** + * {@code Predicate} that always evaluate to true + */ Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true; /** @@ -51,7 +53,9 @@ public interface Model { */ void setAddressBook(ReadOnlyAddressBook addressBook); - /** Returns the AddressBook */ + /** + * Returns the AddressBook + */ ReadOnlyAddressBook getAddressBook(); /** @@ -82,12 +86,20 @@ public interface Model { */ void setPerson(Person target, Person editedPerson); - /** Returns an unmodifiable view of the filtered person list */ + /** + * Returns an unmodifiable view of the filtered person list + */ ObservableList getFilteredPersonList(); /** * Updates the filter of the filtered person list to filter by the given {@code predicate}. + * * @throws NullPointerException if {@code predicate} is null. */ void updateFilteredPersonList(Predicate predicate); + + /** + * Updates the filter of the filtered person list to just the specified person {@code predicate}. + */ + void view(Person clientToView); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index e138f7d1b9d..35789924b67 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -117,7 +117,11 @@ public void addLead(Lead lead) { addressBook.addLead(lead); updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); } - + @Override + public void view(Person clientToView) { + Predicate leadPredicate = person -> person.equals(clientToView); + updateFilteredPersonList(leadPredicate); + } @Override public void setPerson(Person target, Person editedPerson) { requireAllNonNull(target, editedPerson); @@ -158,5 +162,4 @@ public boolean equals(Object other) { && userPrefs.equals(otherModelManager.userPrefs) && filteredPersons.equals(otherModelManager.filteredPersons); } - } diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 79e74ef37c0..1eaac307bd5 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -2,6 +2,7 @@ import java.util.logging.Logger; +import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.MenuItem; @@ -16,6 +17,7 @@ import seedu.address.logic.commands.CommandResult; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.person.Person; /** * The Main Window. Provides the basic application layout containing @@ -28,12 +30,17 @@ public class MainWindow extends UiPart { private final Logger logger = LogsCenter.getLogger(getClass()); private Stage primaryStage; + private Logic logic; // Independent Ui parts residing in this Ui container private PersonListPanel personListPanel; private ResultDisplay resultDisplay; private HelpWindow helpWindow; + private ViewWindow viewWindow; + @FXML + private StackPane viewWindowPlaceholder; + @FXML private StackPane commandBoxPlaceholder; @@ -44,6 +51,10 @@ public class MainWindow extends UiPart { @FXML private StackPane personListPanelPlaceholder; + @FXML + private StackPane clientListPanelPlaceholder; + + @FXML private StackPane resultDisplayPlaceholder; @@ -60,14 +71,15 @@ public MainWindow(Stage primaryStage, Logic logic) { this.primaryStage = primaryStage; this.logic = logic; + // Configure the UI setWindowDefaultSize(logic.getGuiSettings()); setAccelerators(); - helpWindow = new HelpWindow(); } + public Stage getPrimaryStage() { return primaryStage; } @@ -105,7 +117,6 @@ private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) { } }); } - /** * Fills up all the placeholders of this window. */ @@ -163,6 +174,43 @@ private void handleExit() { primaryStage.hide(); } + /** + * Handles the View Command. + */ + @FXML + public void handleView(Person selectedPerson, int displayedIndex) { + logger.info("handleView"); + showViewWindow(selectedPerson, displayedIndex); + } + + + private void showViewWindow(Person selectedPerson, int displayedIndex) { + try { + if (viewWindow != null && viewWindowPlaceholder != null) { + clearViewContent(); + viewWindowPlaceholder.getChildren().add(viewWindow.getRoot()); + personListPanelPlaceholder.setVisible(false); + personListPanelPlaceholder.setManaged(false); + viewWindowPlaceholder.setVisible(true); + viewWindowPlaceholder.setManaged(true); + } else { + + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void clearViewContent() { + viewWindowPlaceholder.getChildren().clear(); + } + + private void hideViewWindow() { + if (viewWindow != null && viewWindowPlaceholder != null) { + viewWindowPlaceholder.setVisible(false); + personListPanelPlaceholder.setVisible(true); + } + } public PersonListPanel getPersonListPanel() { return personListPanel; } @@ -173,9 +221,11 @@ public PersonListPanel getPersonListPanel() { * @see seedu.address.logic.Logic#execute(String) */ private CommandResult executeCommand(String commandText) throws CommandException, ParseException { + try { CommandResult commandResult = logic.execute(commandText); logger.info("Result: " + commandResult.getFeedbackToUser()); + logger.info("reached here: " + logic.getFilteredPersonList()); resultDisplay.setFeedbackToUser(commandResult.getFeedbackToUser()); if (commandResult.isShowHelp()) { @@ -186,6 +236,15 @@ private CommandResult executeCommand(String commandText) throws CommandException handleExit(); } + if (commandResult.checkState().equals("view")) { + ObservableList allPersons = logic.getFilteredPersonList(); + Person selectedPerson = allPersons.get(0); + viewWindow = new ViewWindow(selectedPerson, 1); + + handleView(selectedPerson, 0); + } else { + hideViewWindow(); + } return commandResult; } catch (CommandException | ParseException e) { logger.info("An error occurred while executing command: " + commandText); diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/seedu/address/ui/UiManager.java index fdf024138bc..dd26e9dde76 100644 --- a/src/main/java/seedu/address/ui/UiManager.java +++ b/src/main/java/seedu/address/ui/UiManager.java @@ -1,5 +1,6 @@ package seedu.address.ui; + import java.util.logging.Logger; import javafx.application.Platform; diff --git a/src/main/java/seedu/address/ui/ViewWindow.java b/src/main/java/seedu/address/ui/ViewWindow.java new file mode 100644 index 00000000000..21e8f6317d7 --- /dev/null +++ b/src/main/java/seedu/address/ui/ViewWindow.java @@ -0,0 +1,74 @@ +package seedu.address.ui; + +import java.util.Comparator; +import java.util.logging.Logger; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Region; +import seedu.address.commons.core.LogsCenter; +import seedu.address.model.person.Person; + +/** + * An UI component that displays information of a {@code Person}. + */ +public class ViewWindow extends UiPart { + + private static final String FXML = "ViewWindow.fxml"; + + /** + * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX. + * As a consequence, UI elements' variable names cannot be set to such keywords + * or an exception will be thrown by JavaFX during runtime. + * + * @see The issue on AddressBook level 4 + */ + + private static final Logger logger = LogsCenter.getLogger(ViewWindow.class); + + public final Person person; + + @FXML + private HBox cardPane; + @FXML + private Label name; + @FXML + private Label id; + @FXML + private Label phone; + @FXML + private Label address; + @FXML + private Label email; + @FXML + private FlowPane tags; + + @FXML + private Label otherInfo; + + /** + * Creates a {@code PersonCode} with the given {@code Person} and index to display. + */ + public ViewWindow(Person person, int displayedIndex) { + super(FXML); + this.person = person; + //id.setText(displayedIndex + "."); + name.setText(person.getName().fullName); + phone.setText(person.getPhone().value); + address.setText(person.getAddress().value); + email.setText(person.getEmail().value); + + Label label = new Label(person.getType().value); + if (person.isClient()) { + label.getStyleClass().add("client-label"); + } else { + label.getStyleClass().add("lead-label"); + } + tags.getChildren().add(label); + person.getTags().stream() + .sorted(Comparator.comparing(tag -> tag.tagName)) + .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); + } +} diff --git a/src/main/resources/images/application.png b/src/main/resources/images/application.png new file mode 100644 index 00000000000..97a86c459ea Binary files /dev/null and b/src/main/resources/images/application.png differ diff --git a/src/main/resources/images/email.png b/src/main/resources/images/email.png new file mode 100644 index 00000000000..3fed7b8e8e2 Binary files /dev/null and b/src/main/resources/images/email.png differ diff --git a/src/main/resources/images/home-address.png b/src/main/resources/images/home-address.png new file mode 100644 index 00000000000..54971450e19 Binary files /dev/null and b/src/main/resources/images/home-address.png differ diff --git a/src/main/resources/images/profile.png b/src/main/resources/images/profile.png new file mode 100644 index 00000000000..f0e07c6ff3e Binary files /dev/null and b/src/main/resources/images/profile.png differ diff --git a/src/main/resources/images/smartphone-call.png b/src/main/resources/images/smartphone-call.png new file mode 100644 index 00000000000..99a76415412 Binary files /dev/null and b/src/main/resources/images/smartphone-call.png differ diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css index bfb1cab2a8d..ed71cf5383e 100644 --- a/src/main/resources/view/DarkTheme.css +++ b/src/main/resources/view/DarkTheme.css @@ -338,7 +338,7 @@ } #tags { - -fx-hgap: 7; + -fx-hgap: 10; -fx-vgap: 3; } diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 7778f666a0a..19bf72caec4 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -51,9 +51,9 @@ + - - + diff --git a/src/main/resources/view/ViewWindow.css b/src/main/resources/view/ViewWindow.css new file mode 100644 index 00000000000..22664d187b5 --- /dev/null +++ b/src/main/resources/view/ViewWindow.css @@ -0,0 +1,22 @@ +#cardPane { + -fx-background-color: #FBFBD4; +} + +.label { + -fx-font-family: "Arial"; + -fx-font-size: 18px; + -fx-text-fill: black; +} + +.cell_big_label { + -fx-font-size: 24px; + -fx-font-weight: bold; + -fx-text-fill: black; + -fx-padding: 10px; +} + +.cell_small_label { + -fx-font-size: 18px; + -fx-text-fill: black; + -fx-padding: 5px; +} diff --git a/src/main/resources/view/ViewWindow.fxml b/src/main/resources/view/ViewWindow.fxml new file mode 100644 index 00000000000..b078982cfca --- /dev/null +++ b/src/main/resources/view/ViewWindow.fxml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/seedu/address/logic/commands/AddClientCommandTest.java b/src/test/java/seedu/address/logic/commands/AddClientCommandTest.java index 1fac9c54b19..e00a41583b0 100644 --- a/src/test/java/seedu/address/logic/commands/AddClientCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddClientCommandTest.java @@ -110,7 +110,6 @@ public GuiSettings getGuiSettings() { public void setGuiSettings(GuiSettings guiSettings) { throw new AssertionError("This method should not be called."); } - @Override public Path getAddressBookFilePath() { throw new AssertionError("This method should not be called."); @@ -170,6 +169,11 @@ public ObservableList getFilteredPersonList() { public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + + @Override + public void view(Person personToView) { + throw new AssertionError("This method should not be called."); + } } /** @@ -182,7 +186,6 @@ private class ModelStubWithPerson extends ModelStub { requireNonNull(person); this.person = person; } - @Override public boolean hasPerson(Person person) { requireNonNull(person); @@ -196,18 +199,16 @@ public boolean hasPerson(Person person) { private class ModelStubAcceptingClientAdded extends ModelStub { final ArrayList personsAdded = new ArrayList<>(); - @Override - public boolean hasPerson(Person person) { - requireNonNull(person); - return personsAdded.stream().anyMatch(person::isSamePerson); - } - @Override public void addClient(Client client) { requireNonNull(client); personsAdded.add(client); } - + @Override + public boolean hasPerson(Person person) { + requireNonNull(person); + return personsAdded.stream().anyMatch(person::isSamePerson); + } @Override public ReadOnlyAddressBook getAddressBook() { return new AddressBook(); diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 16b3ef6914d..61e44ccd13f 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -122,7 +122,6 @@ private class ModelStub implements Model { public void setUserPrefs(ReadOnlyUserPrefs userPrefs) { throw new AssertionError("This method should not be called."); } - @Override public ReadOnlyUserPrefs getUserPrefs() { throw new AssertionError("This method should not be called."); @@ -197,6 +196,10 @@ public ObservableList getFilteredPersonList() { public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + @Override + public void view(Person personToView) { + throw new AssertionError("This method should not be called."); + } } /** diff --git a/src/test/java/seedu/address/logic/commands/AddLeadCommandTest.java b/src/test/java/seedu/address/logic/commands/AddLeadCommandTest.java index 671e897f66c..a7774e6542d 100644 --- a/src/test/java/seedu/address/logic/commands/AddLeadCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddLeadCommandTest.java @@ -105,7 +105,6 @@ public ReadOnlyUserPrefs getUserPrefs() { public GuiSettings getGuiSettings() { throw new AssertionError("This method should not be called."); } - @Override public void setGuiSettings(GuiSettings guiSettings) { throw new AssertionError("This method should not be called."); @@ -170,6 +169,10 @@ public ObservableList getFilteredPersonList() { public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + @Override + public void view(Person personToView) { + throw new AssertionError("This method should not be called."); + } } /** diff --git a/src/test/java/seedu/address/logic/commands/CommandResultTest.java b/src/test/java/seedu/address/logic/commands/CommandResultTest.java index 7b8c7cd4546..36849f13d5e 100644 --- a/src/test/java/seedu/address/logic/commands/CommandResultTest.java +++ b/src/test/java/seedu/address/logic/commands/CommandResultTest.java @@ -14,7 +14,7 @@ public void equals() { // same values -> returns true assertTrue(commandResult.equals(new CommandResult("feedback"))); - assertTrue(commandResult.equals(new CommandResult("feedback", false, false))); + assertTrue(commandResult.equals(new CommandResult("feedback", false, false, "feedback"))); // same object -> returns true assertTrue(commandResult.equals(commandResult)); @@ -29,10 +29,10 @@ public void equals() { assertFalse(commandResult.equals(new CommandResult("different"))); // different showHelp value -> returns false - assertFalse(commandResult.equals(new CommandResult("feedback", true, false))); + assertFalse(commandResult.equals(new CommandResult("feedback", true, false, "help"))); // different exit value -> returns false - assertFalse(commandResult.equals(new CommandResult("feedback", false, true))); + assertFalse(commandResult.equals(new CommandResult("feedback", false, true, "exit"))); } @Test @@ -46,10 +46,34 @@ public void hashcode() { assertNotEquals(commandResult.hashCode(), new CommandResult("different").hashCode()); // different showHelp value -> returns different hashcode - assertNotEquals(commandResult.hashCode(), new CommandResult("feedback", true, false).hashCode()); + assertNotEquals(commandResult.hashCode(), new CommandResult("feedback", true, false, "help").hashCode()); // different exit value -> returns different hashcode - assertNotEquals(commandResult.hashCode(), new CommandResult("feedback", false, true).hashCode()); + assertNotEquals(commandResult.hashCode(), new CommandResult("feedback", false, true, "exit").hashCode()); + } + @Test + public void stateTest() { + CommandResult commandResult = new CommandResult("feedback", true, false, "view"); + assertEquals("view", commandResult.checkState()); + } + + @Test + public void notEqualsTest() { + CommandResult commandResult1 = new CommandResult("feedback", true, true, "view"); + CommandResult commandResult2 = new CommandResult("differentFeedback", true, true, "help"); + assertNotEquals(commandResult1, commandResult2); + } + @Test + public void defaultConstructorTest() { + CommandResult commandResult = new CommandResult("feedback"); + assertFalse(commandResult.isShowHelp()); + assertFalse(commandResult.isExit()); + assertEquals("null", commandResult.checkState()); + } + @Test + public void hashCodeConsistencyTest() { + CommandResult commandResult = new CommandResult("feedback", true, false, "state"); + assertEquals(commandResult.hashCode(), commandResult.hashCode()); } @Test diff --git a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java b/src/test/java/seedu/address/logic/commands/ExitCommandTest.java index 9533c473875..b432a8d7c81 100644 --- a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ExitCommandTest.java @@ -14,7 +14,7 @@ public class ExitCommandTest { @Test public void execute_exit_success() { - CommandResult expectedCommandResult = new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true); + CommandResult expectedCommandResult = new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true, "exit"); assertCommandSuccess(new ExitCommand(), model, expectedCommandResult, expectedModel); } } diff --git a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java b/src/test/java/seedu/address/logic/commands/HelpCommandTest.java index 4904fc4352e..bae0e1cd3b8 100644 --- a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/HelpCommandTest.java @@ -14,7 +14,7 @@ public class HelpCommandTest { @Test public void execute_help_success() { - CommandResult expectedCommandResult = new CommandResult(SHOWING_HELP_MESSAGE, true, false); + CommandResult expectedCommandResult = new CommandResult(SHOWING_HELP_MESSAGE, true, false, "help"); assertCommandSuccess(new HelpCommand(), model, expectedCommandResult, expectedModel); } } diff --git a/src/test/java/seedu/address/logic/commands/ViewCommandTest.java b/src/test/java/seedu/address/logic/commands/ViewCommandTest.java new file mode 100644 index 00000000000..837ba1a9ceb --- /dev/null +++ b/src/test/java/seedu/address/logic/commands/ViewCommandTest.java @@ -0,0 +1,67 @@ +package seedu.address.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; +import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; +import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.Messages; +import seedu.address.model.Model; +import seedu.address.model.ModelManager; +import seedu.address.model.UserPrefs; +import seedu.address.model.person.Person; + +/** + * Contains integration tests (interaction with the Model) and unit tests for ListCommand. + */ +public class ViewCommandTest { + + private Model model; + private Model expectedModel; + + @BeforeEach + public void setUp() { + model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + } + + @Test + public void equals() { + Index index1 = Index.fromOneBased(1); + Index index2 = Index.fromOneBased(2); + + ViewCommand viewCommand1 = new ViewCommand(index1); + ViewCommand viewCommand2 = new ViewCommand(index2); + + assertTrue(viewCommand1.equals(viewCommand1)); + + assertFalse(viewCommand1.equals(viewCommand2)); + + assertFalse(viewCommand1.equals(5)); + } + + @Test + public void execute_invalidIndex_throwsCommandException() { + Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); + ViewCommand viewCommand = new ViewCommand(outOfBoundIndex); + + assertCommandFailure(viewCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + @Test + public void execute_validIndexViewPerson_success() { + ViewCommand viewCommand = new ViewCommand(INDEX_FIRST_PERSON); + String expectedMessage = String.format(ViewCommand.MESSAGE_SUCCESS); + Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + Person personToView = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); + expectedModel.view(personToView); + assertCommandSuccess(viewCommand, model, expectedMessage, expectedModel); + } +} + diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index a89cb239f61..c3b56840fdf 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -15,6 +15,7 @@ import org.junit.jupiter.api.Test; +import seedu.address.commons.core.index.Index; import seedu.address.logic.commands.AddClientCommand; import seedu.address.logic.commands.AddLeadCommand; import seedu.address.logic.commands.ClearCommand; @@ -24,7 +25,10 @@ import seedu.address.logic.commands.ExitCommand; import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.HelpCommand; +import seedu.address.logic.commands.ListClientCommand; import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.commands.ListLeadCommand; +import seedu.address.logic.commands.ViewCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.Client; import seedu.address.model.person.Lead; @@ -120,4 +124,19 @@ public void parseCommand_unrecognisedInput_throwsParseException() { public void parseCommand_unknownCommand_throwsParseException() { assertThrows(ParseException.class, MESSAGE_UNKNOWN_COMMAND, () -> parser.parseCommand("unknownCommand")); } + + @Test + public void parseCommand_view() throws Exception { + ViewCommand command = (ViewCommand) parser.parseCommand( + ViewCommand.COMMAND_WORD + " " + 3); + assertEquals(new ViewCommand(Index.fromOneBased(3)), command); + } + @Test + public void parseCommand_listClient() throws Exception { + assertTrue(parser.parseCommand(ListClientCommand.COMMAND_WORD) instanceof ListClientCommand); + } + @Test + public void parseCommand_listLead() throws Exception { + assertTrue(parser.parseCommand(ListLeadCommand.COMMAND_WORD) instanceof ListLeadCommand); + } } diff --git a/src/test/java/seedu/address/logic/parser/ViewCommandParserTest.java b/src/test/java/seedu/address/logic/parser/ViewCommandParserTest.java new file mode 100644 index 00000000000..8e915b1efd4 --- /dev/null +++ b/src/test/java/seedu/address/logic/parser/ViewCommandParserTest.java @@ -0,0 +1,23 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; +import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; + +import org.junit.jupiter.api.Test; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.ViewCommand; +public class ViewCommandParserTest { + private ViewCommandParser parser = new ViewCommandParser(); + + @Test + public void parse_emptyArg_throwsParseException() { + assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewCommand.MESSAGE_USAGE)); + } + @Test + public void parse_validArgs_returnsViewCommand() { + assertParseSuccess(parser, "2", new ViewCommand(Index.fromOneBased(2))); + } + +}