forked from nus-cs2103-AY2425S1/tp
-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Appointment Feature #57
Merged
itsnotsherm
merged 16 commits into
AY2425S1-CS2103T-W11-1a:master
from
reidenong:branch-appointment
Oct 17, 2024
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
7cf64a2
Add appointment feature
reidenong e417307
Fix test cases for appointment feature
reidenong dbc9075
Merge pull request #1 from reidenong/branch-appointment
reidenong 63b067b
Merge branch 'AY2425S1-CS2103T-W11-1a:master' into master
reidenong 4eb5e70
Add AppointmentCommand arg validation
reidenong 6884022
Remove trailing whitespace
reidenong 37bbf30
Remove trailing whitespace
reidenong bb629e3
Remove trailing whitespace
reidenong c2ff1a6
Fix checkstyle errors
reidenong 83f441a
Resolve comment suggestions
reidenong 2a16f56
Merge branch 'master' of https://github.com/reidenong/tp
reidenong 45a47ca
Merge remarks, nric features
reidenong 112a00f
Fixed checkstyle
reidenong a1c50ae
Add appointment to PersonBuilder
reidenong 9ed71d3
Make Appointment unit tests
reidenong a7896c6
Add AppointmentCommandParser unit tests
reidenong File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
src/main/java/seedu/address/logic/commands/AppointmentCommand.java
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. neat implementation, code is readable and variables are grouped nicely, keep it up |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package seedu.address.logic.commands; | ||
|
||
import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; | ||
|
||
import java.util.List; | ||
|
||
import seedu.address.commons.core.index.Index; | ||
import seedu.address.commons.util.ToStringBuilder; | ||
import seedu.address.logic.Messages; | ||
import seedu.address.logic.commands.exceptions.CommandException; | ||
import seedu.address.model.Model; | ||
import seedu.address.model.person.Appointment; | ||
import seedu.address.model.person.Person; | ||
|
||
/** | ||
* Sets or updates an appointment for the person identified by the displayed index from the address book. | ||
*/ | ||
public class AppointmentCommand extends Command { | ||
|
||
public static final String COMMAND_WORD = "appointment"; | ||
|
||
public static final String MESSAGE_USAGE = COMMAND_WORD | ||
+ ": Sets an appointment for the person identified by the index number used in the displayed person list.\n" | ||
+ "Parameters: INDEX (must be a positive integer), a/APPOINTMENT (in the format DD-MM-YYYY HH:MM)\n" | ||
+ "Example: " + COMMAND_WORD + " 1 a/25-12-2024 14:30"; | ||
|
||
public static final String MESSAGE_SET_APPOINTMENT_SUCCESS = "Set Appointment for Person: %1$s"; | ||
public static final String MESSAGE_INVALID_APPOINTMENT_FORMAT = "Please use DD-MM-YYYY HH:MM."; | ||
public static final String MESSAGE_NO_APPOINTMENT_PROVIDED = "Please provide a valid appointment date."; | ||
|
||
private final Index index; | ||
private final String appointmentString; // Store appointment string to convert to LocalDateTime | ||
|
||
/** | ||
* Constructor to create an AppointmentCommand. | ||
* | ||
* @param targetIndex Index of the person to set the appointment for. | ||
* @param appointmentString String of the appointment in the format a/DD-MM-YYYY HH:MM. | ||
*/ | ||
public AppointmentCommand(Index targetIndex, String appointmentString) { | ||
this.index = targetIndex; | ||
this.appointmentString = appointmentString.trim(); | ||
} | ||
|
||
@Override | ||
public CommandResult execute(Model model) throws CommandException { | ||
List<Person> lastShownList = model.getFilteredPersonList(); | ||
|
||
if (this.index.getZeroBased() >= lastShownList.size()) { | ||
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); | ||
} | ||
|
||
Person personToEdit = lastShownList.get(index.getZeroBased()); | ||
Person editedPerson = new Person( | ||
personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(), personToEdit.getNric(), | ||
personToEdit.getAddress(), personToEdit.getRemark(), personToEdit.getTags(), | ||
new Appointment(this.appointmentString)); | ||
model.setPerson(personToEdit, editedPerson); | ||
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); | ||
return new CommandResult("Set appointment for " + personToEdit.getName() + " on " + this.appointmentString); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object other) { | ||
if (other == this) { | ||
return true; | ||
} | ||
|
||
if (!(other instanceof AppointmentCommand)) { | ||
return false; | ||
} | ||
|
||
AppointmentCommand otherCommand = (AppointmentCommand) other; | ||
return index.equals(otherCommand.index) | ||
&& appointmentString.equals(otherCommand.appointmentString); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return new ToStringBuilder(this) | ||
.add("targetIndex", index) | ||
.add("appointmentString", appointmentString) | ||
.toString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
126 changes: 126 additions & 0 deletions
126
src/main/java/seedu/address/logic/parser/AppointmentCommandParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
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.AppointmentCommand; | ||
import seedu.address.logic.parser.exceptions.ParseException; | ||
|
||
/** | ||
* Parses input arguments and creates a new AppointmentCommand object. | ||
*/ | ||
public class AppointmentCommandParser implements Parser<AppointmentCommand> { | ||
|
||
private static final String APPOINTMENT_PREFIX = "a/"; | ||
|
||
/** | ||
* Parses the given {@code String} of arguments in the context of the AppointmentCommand | ||
* and returns an AppointmentCommand object for execution. | ||
* @throws ParseException if the user input does not conform to the expected format. | ||
*/ | ||
public AppointmentCommand parse(String args) throws ParseException { | ||
String trimmedArgs = args.trim(); | ||
|
||
// Split the arguments into components | ||
String[] argParts = trimmedArgs.split("\\s+"); | ||
|
||
// Check if the input has exactly 3 parts: INDEX, a/DATE, TIME | ||
if (argParts.length != 3 || !argParts[1].startsWith(APPOINTMENT_PREFIX)) { | ||
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AppointmentCommand.MESSAGE_USAGE)); | ||
} | ||
|
||
String dayString; | ||
String dayPart; | ||
String monthPart; | ||
String yearPart; | ||
|
||
try { | ||
// Argument parts validation | ||
dayString = argParts[1].substring(2, 12); | ||
|
||
// Extract day, month, and year | ||
dayPart = dayString.substring(0, 2); | ||
monthPart = dayString.substring(3, 5); | ||
yearPart = dayString.substring(6, 10); | ||
|
||
} catch (StringIndexOutOfBoundsException e) { | ||
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AppointmentCommand.MESSAGE_USAGE)); | ||
} | ||
|
||
|
||
// Check if the string is in the correct format (with '-' at the right positions) | ||
if (!dayString.substring(2, 3).equals("-") || !dayString.substring(5, 6).equals("-")) { | ||
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AppointmentCommand.MESSAGE_USAGE)); | ||
} | ||
|
||
int day; | ||
int month; | ||
int year; | ||
try { | ||
day = Integer.parseInt(dayPart); | ||
month = Integer.parseInt(monthPart); | ||
year = Integer.parseInt(yearPart); | ||
} catch (NumberFormatException e) { | ||
throw new ParseException("Invalid date format. Day, month, and year must be numbers."); | ||
} | ||
|
||
// Validate day and month ranges | ||
if (day < 1 || day > 31 || month < 1 || month > 12) { | ||
throw new ParseException("Day and months must be valid."); | ||
} | ||
|
||
// Time validation | ||
String timeString; | ||
String hourPart; | ||
String minutePart; | ||
|
||
try { | ||
timeString = argParts[2]; | ||
hourPart = timeString.substring(0, 2); | ||
minutePart = timeString.substring(3, 5); | ||
} catch (StringIndexOutOfBoundsException e) { | ||
throw new ParseException( | ||
String.format(MESSAGE_INVALID_COMMAND_FORMAT, AppointmentCommand.MESSAGE_USAGE)); | ||
} | ||
|
||
if (!timeString.substring(2, 3).equals(":")) { | ||
throw new ParseException("Invalid time format. Please use HH:MM."); | ||
} | ||
int hour; | ||
int minute; | ||
try { | ||
hour = Integer.parseInt(hourPart); | ||
minute = Integer.parseInt(minutePart); | ||
} catch (NumberFormatException e) { | ||
throw new ParseException("Invalid time format. Hour and minute must be numbers."); | ||
} | ||
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { | ||
throw new ParseException("Hour and minute must be valid."); | ||
} | ||
|
||
// Parse the index | ||
String indexString = argParts[0]; | ||
Index index; | ||
try { | ||
int indexValue = Integer.parseInt(indexString); | ||
if (indexValue <= 0) { | ||
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, | ||
AppointmentCommand.MESSAGE_USAGE)); | ||
} | ||
index = Index.fromZeroBased(indexValue - 1); // Adjust to zero-based index | ||
} catch (NumberFormatException e) { | ||
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AppointmentCommand.MESSAGE_USAGE)); | ||
} | ||
|
||
// Extract and validate the appointment date and time | ||
String appointmentDateTime = trimmedArgs.substring(trimmedArgs.indexOf(APPOINTMENT_PREFIX) + 2).trim(); | ||
|
||
// If appointmentDateTime is not valid, throw an error | ||
if (appointmentDateTime.isEmpty()) { | ||
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AppointmentCommand.MESSAGE_USAGE)); | ||
} | ||
|
||
// Return the constructed AppointmentCommand | ||
return new AppointmentCommand(index, appointmentDateTime); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package seedu.address.model.person; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
import java.time.LocalDateTime; | ||
import java.time.format.DateTimeFormatter; | ||
|
||
/** | ||
* Represents a Person's appointment in the address book. | ||
*/ | ||
public class Appointment { | ||
|
||
public static final String MESSAGE_CONSTRAINTS = "Appointments should be of the format DD-MM-YYYY HH:MM"; | ||
|
||
public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm"); | ||
|
||
public final LocalDateTime value; | ||
|
||
/** | ||
* Constructs an {@code Appointment}. | ||
* | ||
* @param dateTimeString A valid appointment date string. | ||
*/ | ||
public Appointment(String dateTimeString) { | ||
requireNonNull(dateTimeString); | ||
this.value = LocalDateTime.parse(dateTimeString, FORMATTER); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return value.format(FORMATTER); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object other) { | ||
if (other == this) { | ||
return true; | ||
} | ||
|
||
if (!(other instanceof Appointment)) { | ||
return false; | ||
} | ||
|
||
Appointment otherAppointment = (Appointment) other; | ||
return (value.toString()).equals(otherAppointment.value.toString()); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return value.hashCode(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch, thanks for rectifying this