diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..25569fc --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,32 @@ +version: 2 +jobs: + build: + working_directory: ~/SEG2105-Olympus/OlympusServices + docker: + - image: circleci/android:api-28-alpha + environment: + JVM_OPTS: -Xmx3200m + steps: + - checkout: + path: ~/SEG2105-Olympus + - restore_cache: + key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }} + - run: + name: Chmod permissions + command: sudo chmod +x ./gradlew + - run: + name: Download Dependencies + command: ./gradlew androidDependencies + - save_cache: + paths: + - ~/.gradle + key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }} + - run: + name: Run UnitTest + command: ./gradlew test + - store_artifacts: + path: app/build/outputs/apk/debug/ + destination: apks/ + - store_test_results: + path: app/build/test-results + diff --git a/Deliverable1.zip b/Deliverable1.zip new file mode 100644 index 0000000..fd97b0b Binary files /dev/null and b/Deliverable1.zip differ diff --git a/Deliverable2.zip b/Deliverable2.zip new file mode 100644 index 0000000..a5338f4 Binary files /dev/null and b/Deliverable2.zip differ diff --git a/Deliverable3.zip b/Deliverable3.zip new file mode 100644 index 0000000..8124e2f Binary files /dev/null and b/Deliverable3.zip differ diff --git a/OlympusServices/.idea/caches/build_file_checksums.ser b/OlympusServices/.idea/caches/build_file_checksums.ser index 24e3c6b..d94de5c 100644 Binary files a/OlympusServices/.idea/caches/build_file_checksums.ser and b/OlympusServices/.idea/caches/build_file_checksums.ser differ diff --git a/OlympusServices/.idea/misc.xml b/OlympusServices/.idea/misc.xml index 99202cc..cc51e58 100644 --- a/OlympusServices/.idea/misc.xml +++ b/OlympusServices/.idea/misc.xml @@ -25,7 +25,7 @@ - + diff --git a/OlympusServices/.idea/vcs.xml b/OlympusServices/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/OlympusServices/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/OlympusServices/app/build.gradle b/OlympusServices/app/build.gradle index 4a8aefa..313fb68 100644 --- a/OlympusServices/app/build.gradle +++ b/OlympusServices/app/build.gradle @@ -16,18 +16,32 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + testOptions { + unitTests { + includeAndroidResources = true + } + } } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:design:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' + testImplementation 'androidx.test:core:1.0.0' + testImplementation 'org.mockito:mockito-core:1.10.19' + testImplementation 'org.robolectric:robolectric:4.0-alpha-3-SNAPSHOT' androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test:rules:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + androidTestImplementation 'org.hamcrest:hamcrest-library:1.3' implementation 'com.jaredrummler:material-spinner:1.2.5' implementation 'com.android.support:design:28.0.0-alpha3' implementation 'com.rengwuxian.materialedittext:library:2.1.4' - + implementation 'com.android.support:recyclerview-v7:28.0.0' +} + +repositories { + maven { url "https://oss.sonatype.org/content/repositories/snapshots" } } diff --git a/OlympusServices/app/src/main/AndroidManifest.xml b/OlympusServices/app/src/main/AndroidManifest.xml index 167ae5c..425603f 100644 --- a/OlympusServices/app/src/main/AndroidManifest.xml +++ b/OlympusServices/app/src/main/AndroidManifest.xml @@ -9,15 +9,14 @@ - + android:screenOrientation="portrait"> @@ -29,13 +28,52 @@ android:name="preloaded_fonts" android:resource="@array/preloaded_fonts" /> - - - - - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OlympusServices/app/src/main/ic_launcher-web.png b/OlympusServices/app/src/main/ic_launcher-web.png new file mode 100644 index 0000000..547c096 Binary files /dev/null and b/OlympusServices/app/src/main/ic_launcher-web.png differ diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Admin.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Admin.java new file mode 100644 index 0000000..7f8bdfa --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Admin.java @@ -0,0 +1,32 @@ +package com.uottawa.olympus.olympusservices; + +/** + * The class Admin is a child of the class userType. The class gives + * admin permission over the app such that the user can add and delete services + * and can add and delete other users from the database of the app. + * + */ + +public class Admin extends UserType { + + /** + * The constructor for the admin object with predefined fields. + * There should only be one admin object for the entire app. + */ + Admin(){ + super("admin", "admin", "Admin", "Admin"); + } + + Admin(String hash, String salt){ + super("admin", hash, salt, "Admin", "Admin"); + } + + /** + * The getRole() method returns a string "Admin" + * the app gets role of user type objects for access + * app permission purposes. + * + * @return String object "Admin" + */ + public String getRole(){ return "Admin"; } +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/AdminServicesList.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/AdminServicesList.java new file mode 100644 index 0000000..ad967ff --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/AdminServicesList.java @@ -0,0 +1,213 @@ +package com.uottawa.olympus.olympusservices; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.Iterator; +import java.util.List; + +/** + * Creates the view and dialog listener for List of services + * which the admin can view and manipulate. + * + */ +public class AdminServicesList extends AppCompatActivity implements NewServiceDialogFragment.NoticeDialogListener, EditServiceDialogFragment.NoticeDialogListener{ + + //field for RecyclerView + private RecyclerView mRecyclerView; + //field for adapter of Recycler view + private RecyclerView.Adapter mAdapter; + //field for layout manager of Recyler view. + private RecyclerView.LayoutManager mLayoutManager; + + /** + * On creation loads up the xml, and generates the services list, + * and fillsout the recylerView fields. + * + * @param savedInstanceState Bundle to transfer information. + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_admin_services_list); + DBHelper dbHelper = new DBHelper(this); + List serviceslist = dbHelper.getAllServices(); + Service[] services = new Service[(serviceslist.size())]; + Iterator iter = serviceslist.iterator(); + for (int i=0; i { + + private Service[] services; + private Context context; + + // Provide a reference to the views for each data item + // Complex data items may need more than one view per item, and + // you provide access to all the views for a data item in a view holder + + // Provide a suitable constructor (depends on the kind of dataset) + public MyAdapter(Service[] services, Context context) { + this.services = services; + } + + // Create new views (invoked by the layout manager) + @NonNull + @Override + public ServicesHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.service_list_item, parent, false); + ServicesHolder vh = new ServicesHolder(v); + return vh; + } + + // Replace the contents of a view (invoked by the layout manager) + @Override + public void onBindViewHolder(ServicesHolder holder, int position) { + Service service = services[position]; + holder.name.setText(service.getName()); + holder.rate.setText(String.format("$%,.2f", service.getRate())); + + + + } + + // Return the size of your dataset (invoked by the layout manager) + @Override + public int getItemCount() { + return services.length; + } + + class ServicesHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ + + TextView name; + TextView rate; + + public ServicesHolder(View row){ + super(row); + name = row.findViewById(R.id.Name); + rate = row.findViewById(R.id.Rate); + row.setOnClickListener(this); + } + @Override + public void onClick(View view) { + TextView nameview = (TextView)view.findViewById(R.id.Name); + String name = nameview.getText().toString(); + editService(view, name); + + } + + + } + + + } + +} \ No newline at end of file diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/AdminWelcome.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/AdminWelcome.java new file mode 100644 index 0000000..f8e2861 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/AdminWelcome.java @@ -0,0 +1,76 @@ +package com.uottawa.olympus.olympusservices; + +import android.content.Intent; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; + +/** + * The Admin Welcome class is the welcome + * screen for admin users when they have logged into the + * app. The admin welcome screen has features such as the + * user list and service list which it can only access. + * + */ + +public class AdminWelcome extends AppCompatActivity { + + /** + * Creates the xml pages for the class object + * on creation of the object. + * + * @param savedInstanceState Bundle for transfer of data. + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_admin_welcome); + + } + + /** + * Override so that nothing occurs when pressing the + * back button on this activity of the app. + * + */ + @Override + public void onBackPressed(){ + } + + /** + * Logs out the user and returns them back to + * main activity. End all current user activity + * for security purposes. + * + * @param view View object of current activity. + */ + public void LogOut(View view){ + Intent intent = new Intent(getApplicationContext(), Main.class); + startActivity(intent); + finish(); + } + + /** + * On click of list of user button that goes to + * UserList screen for the admin to edit the user list + * of the app. + * + * @param view View object of current activity + */ + public void goToUsers(View view){ + Intent intent = new Intent(getApplicationContext(), UsersList.class); + startActivity(intent); + } + + /** + * On click of list of services button goes to + * ServiceList screen for the admin to edit the + * service list of the app. + * + * @param view + */ + public void goToServices(View view){ + Intent intent = new Intent(getApplicationContext(), AdminServicesList.class); + startActivity(intent); + } +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Appointment.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Appointment.java new file mode 100644 index 0000000..536383e --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Appointment.java @@ -0,0 +1,12 @@ +package com.uottawa.olympus.olympusservices; + +/** + * This class is the class for Appointments + * which has not been implemented yet. This + * feature shall be expanded upon next deliverable. + * + */ +public class Appointment { + Service service; + ServiceProvider provider; +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Booking.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Booking.java new file mode 100644 index 0000000..76144a5 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Booking.java @@ -0,0 +1,154 @@ +package com.uottawa.olympus.olympusservices; + +public class Booking { + private int starth; + private int startmin; + private int endh; + private int endmin; + private int day; + private int month; + private int year; + private ServiceProvider serviceprovider; //username + private HomeOwner homeowner; //username + private Service service; + public enum Status { + PENDING{ + @Override + public String toString() { + return "Pending"; + } + }, + CONFIRMED{ + @Override + public String toString() { + return "Confirmed"; + } + }, + CANCELLED{ + @Override + public String toString() { + return "Cancelled"; + } + } + } + private Status status; + + private int rating; //out of 5 + private String comment; + + public Booking(int starth, int startmin, int endh, int endmin, int day, int month, int year, + ServiceProvider serviceprovider, HomeOwner homeowner, Service service){ + this.starth = starth; + this.startmin = startmin; + this.endh = endh; + this.endmin = endmin; + this.day = day; + this.month = month; + this.year = year; + this.serviceprovider = serviceprovider; + this.homeowner = homeowner; + this.service = service; + this.status = Status.PENDING; + } + + + public int getStarth() { + return starth; + } + + public void setStarth(int starth) { + this.starth = starth; + } + + public int getStartmin() { + return startmin; + } + + public void setStartmin(int startmin) { + this.startmin = startmin; + } + + public int getEndh() { + return endh; + } + + public void setEndh(int endh) { + this.endh = endh; + } + + public int getEndmin() { + return endmin; + } + + public void setEndmin(int endmin) { + this.endmin = endmin; + } + + public int getDay() { + return day; + } + + public void setDay(int day) { + this.day = day; + } + + public int getMonth() { + return month; + } + + public void setMonth(int month) { + this.month = month; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } + + public ServiceProvider getServiceprovider() { + return serviceprovider; + } + + public void setServiceprovider(ServiceProvider serviceprovider) { + this.serviceprovider = serviceprovider; + } + + public HomeOwner getHomeowner() { + return homeowner; + } + + public void setHomeowner(HomeOwner homeowner) { + this.homeowner = homeowner; + } + + public Service getService(){ return service; } + + public void setService(Service service) { this.service = service;} + + public void setStatus(Status status){ + this.status = status; + } + + public Status getStatus(){ + return this.status; + } + + public int getRating() { + return rating; + } + + public void setRating(int rating) { + this.rating = rating; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Bookings.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Bookings.java new file mode 100644 index 0000000..4a211eb --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Bookings.java @@ -0,0 +1,378 @@ +package com.uottawa.olympus.olympusservices; + +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.support.annotation.NonNull; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.SwitchCompat; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class Bookings extends AppCompatActivity { + + //field for RecyclerView + private RecyclerView mRecyclerView; + //field for adapter of Recycler view + private RecyclerView.Adapter mAdapter; + //field for layout manager of Recyler view. + private RecyclerView.LayoutManager mLayoutManager; + + String username; + DBHelper dbhelper; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_bookings); + Bundle bundle = getIntent().getExtras(); + username = bundle.getString("username"); + dbhelper = new DBHelper(this); + + List booking = (List)dbhelper.findBookings(username); + Collections.reverse(booking); + Booking[] bookings = new Booking[booking.size()]; + bookings = booking.toArray(bookings); + Booking[] mostRecentBookings = new Booking[bookings.length]; + + /* //mock data + Booking[] bookings = {new Booking(5, 5, 6, 6, 2, 3, 2019, (ServiceProvider)dbhelper.findUserByUsername("testing"), + (HomeOwner)dbhelper.findUserByUsername("tester"), dbhelper.findService("service1"))}; + */ + mRecyclerView = (RecyclerView) findViewById(R.id.Bookings); + mLayoutManager = new LinearLayoutManager(this); + mRecyclerView.setLayoutManager(mLayoutManager); + mAdapter = new MyAdapter(bookings, this); + mRecyclerView.setAdapter(mAdapter); + + SwitchCompat toggle = findViewById(R.id.Switch); + toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + List booking = (List)dbhelper.findBookings(username); + Booking[] bookings = new Booking[booking.size()]; + bookings = booking.toArray(bookings); + mAdapter = new MyAdapter(bookings, Bookings.this); + mRecyclerView.setAdapter(mAdapter); + mAdapter.notifyDataSetChanged(); + } else { + List booking = (List)dbhelper.findNonCancelledBookings(username); + Booking[] bookings = new Booking[booking.size()]; + bookings = booking.toArray(bookings); + mAdapter = new MyAdapter(bookings, Bookings.this); + mRecyclerView.setAdapter(mAdapter); + mAdapter.notifyDataSetChanged(); + } + } + }); + + } + + /** + * Override so that previous screen refreshes when pressing the + * back button on this activity of the app. + * + */ + @Override + public void onBackPressed(){ + Intent intent; + if(dbhelper.findUserByUsername(username).getRole().equals("ServiceProvider")){ + intent = new Intent(getApplicationContext(),ServiceProviderWelcome.class); + } + else{ + intent = new Intent(getApplicationContext(),Welcome.class); + } + + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + + + public class MyAdapter extends RecyclerView.Adapter { + + private Booking[] bookings; + private Context context; + + // Provide a reference to the views for each data item + // Complex data items may need more than one view per item, and + // you provide access to all the views for a data item in a view holder + + // Provide a suitable constructor (depends on the kind of dataset) + public MyAdapter(Booking[] bookings, Context context) { + this.bookings = bookings; + } + + // Create new views (invoked by the layout manager) + @NonNull + @Override + public BookingHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.booking_list_item, parent, false); + BookingHolder vh = new BookingHolder(v); + return vh; + } + + // Replace the contents of a view (invoked by the layout manager) + @Override + public void onBindViewHolder(BookingHolder holder, int position) { + Booking booking = bookings[position]; + holder.serviceprovider.setText(booking.getServiceprovider().getFirstname()+" "+booking.getServiceprovider().getLastname()+", "+booking.getServiceprovider().getCompanyname()); + holder.homeowner.setText(booking.getHomeowner().getFirstname()+" "+booking.getHomeowner().getLastname()); + holder.service.setText(booking.getService().getName()); + String day; + String month; + String year = booking.getYear()+""; + if(booking.getDay()<10){ + day = "0"+booking.getDay(); + } + else{ + day = booking.getDay()+""; + } + if(booking.getMonth()<10){ + month = "0"+booking.getMonth(); + } + else{ + month = booking.getMonth()+""; + } + + holder.date.setText(month+"/"+day+"/"+year); + holder.start.setText(formatTime(booking.getStarth(), booking.getStartmin())); + holder.end.setText(formatTime(booking.getEndh(), booking.getEndmin())); + holder.status.setText(booking.getStatus().toString()); + holder.ho = booking.getHomeowner().getUsername(); + holder.sp = booking.getServiceprovider().getUsername(); + + + } + + // Return the size of your dataset (invoked by the layout manager) + @Override + public int getItemCount() { + return bookings.length; + } + + class BookingHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ + + TextView homeowner; + TextView serviceprovider; + TextView service; + TextView date; + TextView start; + TextView end; + TextView status; + String ho; + String sp; + int starth; + int startmin; + int endh; + int endmin; + int month; + int day; + int year; + + public BookingHolder(View row){ + super(row); + homeowner = row.findViewById(R.id.HomeOwnerName); + serviceprovider = row.findViewById(R.id.ServiceProviderName); + service = row.findViewById(R.id.ServiceName); + date = row.findViewById(R.id.DateName); + start = row.findViewById(R.id.StartTime); + end = row.findViewById(R.id.EndTime); + status = row.findViewById(R.id.StatusName); + + + row.setOnClickListener(this); + } + @Override + public void onClick(View view) { + if(dbhelper.findUserByUsername(username).getRole()=="ServiceProvider"){ + AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(Bookings.this); + alertDialogBuilder.setMessage("Cancel or Confirm your booking"); + alertDialogBuilder.setPositiveButton("Confirm Booking", + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface arg0, int arg1) { + int[] times = parseTime(start.getText().toString(), end.getText().toString()); + starth = times[0]; + startmin = times[1]; + endh = times[2]; + endmin = times[3]; + String[] dates = date.getText().toString().split("/"); + month = Integer.parseInt(dates[0].replaceAll("\\s+","")); + day = Integer.parseInt(dates[1].replaceAll("\\s+","")); + year = Integer.parseInt(dates[2].replaceAll("\\s+","")); + if(dbhelper.confirmBooking(new Booking(starth, startmin, endh, endmin, day, month, year, (ServiceProvider)dbhelper.findUserByUsername(sp), + (HomeOwner)dbhelper.findUserByUsername(ho), + new Service(service.getText().toString(), 5)))){ + + Toast.makeText(Bookings.this,"Booking is confirmed",Toast.LENGTH_LONG).show(); + Bookings.this.recreate(); + } + else{ + Toast.makeText(Bookings.this,"Booking could not be confirmed",Toast.LENGTH_LONG).show(); + } + + } + }); + + alertDialogBuilder.setNegativeButton("Cancel Booking", + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + int[] times = parseTime(start.getText().toString(), end.getText().toString()); + starth = times[0]; + startmin = times[1]; + endh = times[2]; + endmin = times[3]; + String[] dates = date.getText().toString().split("/"); + month = Integer.parseInt(dates[0].replaceAll("\\s+","")); + day = Integer.parseInt(dates[1].replaceAll("\\s+","")); + year = Integer.parseInt(dates[2].replaceAll("\\s+","")); + if(dbhelper.cancelBooking(new Booking(starth, startmin, endh, endmin, day, month, year, (ServiceProvider)dbhelper.findUserByUsername(sp), + (HomeOwner)dbhelper.findUserByUsername(ho), + new Service(service.getText().toString(), 5)))){ + Toast.makeText(Bookings.this,"Booking is cancelled",Toast.LENGTH_LONG).show(); + Bookings.this.recreate(); + } + else{ + Toast.makeText(Bookings.this,"Booking could not be cancelled",Toast.LENGTH_LONG).show(); + } + } + }); + + AlertDialog alertDialog = alertDialogBuilder.create(); + alertDialog.show(); + } + else{ + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(Bookings.this); + alertDialogBuilder.setView(R.layout.rating_item); + alertDialogBuilder.setPositiveButton("Rate Booking", + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface arg0, int arg1) { + int[] times = parseTime(start.getText().toString(), end.getText().toString()); + starth = times[0]; + startmin = times[1]; + endh = times[2]; + endmin = times[3]; + String[] dates = date.getText().toString().split("/"); + month = Integer.parseInt(dates[0].replaceAll("\\s+","")); + day = Integer.parseInt(dates[1].replaceAll("\\s+","")); + year = Integer.parseInt(dates[2].replaceAll("\\s+","")); + RadioGroup ratingselect = ((AlertDialog) arg0).findViewById(R.id.RatingSelect); + int selectedId = ratingselect.getCheckedRadioButtonId(); + RadioButton ratingpicked; + EditText comment = ((AlertDialog) arg0).findViewById(R.id.Comment); + if(selectedId!=-1 && !comment.getText().toString().equals("")){ + ratingpicked = (RadioButton)((AlertDialog) arg0).findViewById(selectedId); + double rating = Double.parseDouble(ratingpicked.getText().toString()); + + Booking booking = new Booking(starth, startmin, endh, endmin, day, month, year, (ServiceProvider)dbhelper.findUserByUsername(sp), + (HomeOwner)dbhelper.findUserByUsername(ho), + new Service(service.getText().toString(), 5)); + if(!dbhelper.addRating(booking, rating, comment.getText().toString())){ + Toast.makeText(Bookings.this, "Rating cannot be added before the appointment", Toast.LENGTH_SHORT).show(); + } + else{ + Bookings.this.recreate(); + } + + } + else{ + Toast.makeText(Bookings.this, "Rating and comment must be filled in", Toast.LENGTH_SHORT).show(); + } + + } + }); + + alertDialogBuilder.setNegativeButton("Cancel Booking", + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + int[] times = parseTime(start.getText().toString(), end.getText().toString()); + starth = times[0]; + startmin = times[1]; + endh = times[2]; + endmin = times[3]; + String[] dates = date.getText().toString().split("/"); + month = Integer.parseInt(dates[0].replaceAll("\\s+","")); + day = Integer.parseInt(dates[1].replaceAll("\\s+","")); + year = Integer.parseInt(dates[2].replaceAll("\\s+","")); + if(dbhelper.cancelBooking(new Booking(starth, startmin, endh, endmin, day, month, year, (ServiceProvider)dbhelper.findUserByUsername(sp), + (HomeOwner)dbhelper.findUserByUsername(ho), + new Service(service.getText().toString(), 5)))){ + Toast.makeText(Bookings.this,"Booking is cancelled",Toast.LENGTH_LONG).show(); + Bookings.this.recreate(); + } + else{ + Toast.makeText(Bookings.this,"Booking could not be cancelled",Toast.LENGTH_LONG).show(); + } + } + }); + + AlertDialog alertDialog = alertDialogBuilder.create(); + alertDialog.show(); + + } + + + } + + + } + + + } + private String formatTime(int hours, int minutes){ + String time = ""; + if(hours<10){ + time = time+"0"+hours+":"; + }else{ + time = time+hours+":"; + } + if (minutes<10){ + time = time+"0"+minutes; + } + else { + time = time+minutes; + } + return time; + } + + + private int[] parseTime(String startTime, String endTime){ + int[] times = new int[4]; + if(startTime.equals("START")){ + times[0]=0; + times[1]=0; + }else{ + times[0] = Integer.parseInt(startTime.substring(0,2)); + times[1] = Integer.parseInt(startTime.substring(3)); + } + if(endTime.equals("END")){ + times[2]=0; + times[3]=0; + }else{ + times[2] = Integer.parseInt(endTime.substring(0,2)); + times[3] = Integer.parseInt(endTime.substring(3)); + } + return times; + } +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DBHelper.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DBHelper.java new file mode 100644 index 0000000..7976cb8 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DBHelper.java @@ -0,0 +1,2018 @@ +package com.uottawa.olympus.olympusservices; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.database.Cursor; +import android.content.ContentValues; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.LinkedList; +import java.util.List; +import java.util.GregorianCalendar; + +import com.uottawa.olympus.olympusservices.Booking.Status; + +/** + * The class DBHelper allows the Android application to access and perform + * CRUD (Create, Read, Update, Delete) operations on the tables of the SQLite database. + * There is currently one table of all users' login information and names. + * Table of service providers and services to come soon. + * + * To use, create an object of this class with the current activity as context. + * + */ + +public class DBHelper extends SQLiteOpenHelper { + + //version of db used for update method + private static final int DB_VERSION = 7; + //name of db in app data + private static final String DB_NAME = "UsersDB.db"; + + //has the data been added? + private static boolean setUp = false; + + //SQLiteDatabase for reading + private static SQLiteDatabase readDB; + + //SQLiteDatabase for writing + private static SQLiteDatabase writeDB; + + //name of table containing user login information and names + private static final String TABLE_LOGIN = "userInfo"; + //columns of TABLE_LOGIN + private static final String COLUMN_USERNAME = "username"; + private static final String COLUMN_PASSWORD = "password"; //actually stores password hash + private static final String COLUMN_FIRSTNAME = "firstName"; + private static final String COLUMN_LASTNAME = "lastName"; + private static final String COLUMN_USERTYPE = "userType"; + private static final String COLUMN_ADDRESS = "address"; + private static final String COLUMN_PHONE = "phone"; + private static final String COLUMN_COMPANY = "company"; + private static final String COLUMN_LICENSED = "licensed"; + private static final String COLUMN_DESCRIPTION = "description"; + private static final String COLUMN_SALT = "salt"; + + //name of table containing services and rates + private static final String TABLE_SERVICES = "services"; + //columns of TABLE_SERVICES + private static final String COLUMN_SERVICE = "service"; + private static final String COLUMN_RATE = "rate"; + + //name of table containing service provider information + private static final String TABLE_SERVICEPROVIDERS = "serviceProviders"; + //columns of TABLE_SERVICEPROVIDERS + private static final String COLUMN_SERVICEPROVIDERNAME = "username"; + private static final String COLUMN_SERVICEPROVIDERSERVICE = "service"; + private static final String COLUMN_AVERAGERATING = "averageRating"; + private static final String COLUMN_RATERS = "raters"; + private static final String COLUMN_ACTIVE = "active"; + + //name of table containing service provider availability + //availability is stored as number of minutes from 00:00 + private static final String TABLE_AVAILABILITY = "availability"; + //columns of TABLE_AVAILABILITY + private static final String COLUMN_AVAILABILITYNAME = "username"; + private static final String COLUMN_MONSTART = "mondaystart"; + private static final String COLUMN_MONEND = "mondayend"; + private static final String COLUMN_TUESTART = "tuesdaystart"; + private static final String COLUMN_TUEEND = "tuesdayend"; + private static final String COLUMN_WEDSTART = "wednesdaystart"; + private static final String COLUMN_WEDEND = "wednesdayend"; + private static final String COLUMN_THUSTART = "thursdaystart"; + private static final String COLUMN_THUEND = "thursdayend"; + private static final String COLUMN_FRISTART = "fridaystart"; + private static final String COLUMN_FRIEND = "fridayend"; + private static final String COLUMN_SATSTART = "saturdaystart"; + private static final String COLUMN_SATEND = "saturdayend"; + private static final String COLUMN_SUNSTART = "sundaystart"; + private static final String COLUMN_SUNEND = "sundayend"; + + //name of table containing booking + private static final String TABLE_BOOKINGS = "bookings"; + //columns of TABLE_BOOKING + private static final String COLUMN_BOOKINGSERVICEPROVIDER = "serviceProvider"; + private static final String COLUMN_BOOKINGHOMEOWNER = "homeOwner"; + private static final String COLUMN_BOOKINGSERVICE = "service"; + private static final String COLUMN_BOOKINGYEAR = "year"; + private static final String COLUMN_BOOKINGMONTH = "month"; + private static final String COLUMN_BOOKINGDATE = "day"; + private static final String COLUMN_BOOKINGSTART = "starttime"; + private static final String COLUMN_BOOKINGEND = "endtime"; + private static final String COLUMN_BOOKINGSTATUS = "status"; + private static final String COLUMN_RATING = "rating"; + private static final String COLUMN_COMMENT = "comment"; + + /** + * Creates an instance of DBHelper to allow activities to access and + * perform CRUD operations on the database via DBHelper's methods + * + * @param context current activity calling DBHelper + */ + public DBHelper(Context context){ + super(context, DB_NAME, null, DB_VERSION); + //since these methods take a while we will call them once and store the returned dbs + readDB = this.getReadableDatabase(); + writeDB = this.getWritableDatabase(); + + addUser(new Admin()); + + if (!setUp){ + setUp(); + setUp = true; + } + } + + @Override + public void onCreate(SQLiteDatabase db){ + + //making the table containing user login information + String CREATE_LOGIN_TABLE = "CREATE TABLE "+ TABLE_LOGIN + "(" + + COLUMN_USERNAME + " TEXT UNIQUE NOT NULL PRIMARY KEY ON CONFLICT ROLLBACK," + + COLUMN_PASSWORD + " TEXT," + + COLUMN_FIRSTNAME + " TEXT DEFAULT 'FirstName'," + + COLUMN_LASTNAME + " TEXT DEFAULT 'LastName'," + + COLUMN_USERTYPE + " TEXT NOT NULL, " + + COLUMN_ADDRESS + " TEXT, " + + COLUMN_PHONE + " TEXT, " + + COLUMN_COMPANY + " TEXT, " + + COLUMN_LICENSED + " TEXT, " + + COLUMN_DESCRIPTION + " TEXT, " + + COLUMN_SALT + " TEXT " + + ")"; + db.execSQL(CREATE_LOGIN_TABLE); + + //making the table containing services and their rates + String CREATE_SERVICES_TABLE = "CREATE TABLE "+ TABLE_SERVICES + "(" + + COLUMN_SERVICE + " TEXT UNIQUE NOT NULL PRIMARY KEY ON CONFLICT ROLLBACK," + + COLUMN_RATE + " REAL DEFAULT 0.0" + ")"; + db.execSQL(CREATE_SERVICES_TABLE); + + //making the table containing service providers and offered services + String CREATE_SERVICEPROVIDERS_TABLE = "CREATE TABLE "+ TABLE_SERVICEPROVIDERS + "(" + + COLUMN_SERVICEPROVIDERNAME + " TEXT, " + + COLUMN_SERVICEPROVIDERSERVICE + " TEXT, " + + COLUMN_AVERAGERATING + " REAL DEFAULT 0, " + + COLUMN_RATERS + " REAL DEFAULT 0, " + + COLUMN_ACTIVE + " TEXT DEFAULT 'active', " + //service provider name is foreign key + + " FOREIGN KEY(" + COLUMN_SERVICEPROVIDERNAME + + ") REFERENCES " + TABLE_LOGIN + "(" + COLUMN_USERNAME +"), " + //service is also foreign key + + " FOREIGN KEY(" + COLUMN_SERVICEPROVIDERSERVICE + + ") REFERENCES " + TABLE_SERVICES + "(" + COLUMN_SERVICE +") " + + ")"; + db.execSQL(CREATE_SERVICEPROVIDERS_TABLE); + + //making the table containing services and their rates + String CREATE_AVAILABILITY_TABLE = "CREATE TABLE "+ TABLE_AVAILABILITY + "(" + + COLUMN_AVAILABILITYNAME + " TEXT UNIQUE NOT NULL PRIMARY KEY ON CONFLICT ROLLBACK, " + + COLUMN_MONSTART + " REAL, " + + COLUMN_MONEND + " REAL, " + + COLUMN_TUESTART + " REAL, " + + COLUMN_TUEEND + " REAL, " + + COLUMN_WEDSTART + " REAL, " + + COLUMN_WEDEND + " REAL, " + + COLUMN_THUSTART + " REAL, " + + COLUMN_THUEND + " REAL, " + + COLUMN_FRISTART + " REAL, " + + COLUMN_FRIEND + " REAL, " + + COLUMN_SATSTART + " REAL, " + + COLUMN_SATEND + " REAL, " + + COLUMN_SUNSTART + " REAL, " + + COLUMN_SUNEND + " REAL)"; + db.execSQL(CREATE_AVAILABILITY_TABLE); + + //making the table containing bookings + String CREATE_BOOKING_TABLE = "CREATE TABLE "+ TABLE_BOOKINGS + "(" + + COLUMN_BOOKINGSERVICEPROVIDER + " TEXT," + + COLUMN_BOOKINGHOMEOWNER + " TEXT," + + COLUMN_BOOKINGSERVICE + " TEXT, " + + COLUMN_BOOKINGYEAR + " REAL," + + COLUMN_BOOKINGMONTH + " REAL, " + + COLUMN_BOOKINGDATE + " REAL, " + + COLUMN_BOOKINGSTART + " REAL, " + + COLUMN_BOOKINGEND + " REAL, " + + COLUMN_BOOKINGSTATUS + " TEXT, " + + COLUMN_RATING + " REAL DEFAULT 0, " + + COLUMN_COMMENT + " TEXT DEFAULT ''" + + ")"; + db.execSQL(CREATE_BOOKING_TABLE); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){ + switch(oldVersion){ + case 1: //going from db version 1 to 2 + //change usertype of Users to Homeowner + ContentValues values = new ContentValues(); + values.put(COLUMN_USERTYPE, "HomeOwner"); + db.update(TABLE_LOGIN, values, COLUMN_USERTYPE + " = ?", new String[]{"User"}); + + //if services table is not created, create it + db.execSQL("CREATE TABLE IF NOT EXISTS "+ TABLE_SERVICES + "(" + + COLUMN_SERVICE + " TEXT UNIQUE NOT NULL PRIMARY KEY ON CONFLICT ROLLBACK," + + COLUMN_RATE + " REAL DEFAULT 0.0" + ")"); + + case 2: //going from db versions 1-2 to 3 + db.execSQL("CREATE TABLE IF NOT EXISTS "+ TABLE_SERVICEPROVIDERS + "(" + + COLUMN_SERVICEPROVIDERNAME + " TEXT NOT NULL, " + + COLUMN_SERVICEPROVIDERSERVICE + " TEXT NOT NULL, " + //service provider name is foreign key + + " FOREIGN KEY(" + COLUMN_SERVICEPROVIDERNAME + + ") REFERENCES " + TABLE_LOGIN + "(" + COLUMN_USERNAME +"), " + //service is also foreign key + + " FOREIGN KEY(" + COLUMN_SERVICEPROVIDERSERVICE + + ") REFERENCES " + TABLE_SERVICES + "(" + COLUMN_SERVICE +") " + + ")"); + db.execSQL("CREATE TABLE IF NOT EXISTS "+ TABLE_AVAILABILITY + "(" + + COLUMN_AVAILABILITYNAME + " TEXT UNIQUE NOT NULL PRIMARY KEY ON CONFLICT ROLLBACK, " + + COLUMN_MONSTART + " REAL, " + + COLUMN_MONEND + " REAL, " + + COLUMN_TUESTART + " REAL, " + + COLUMN_TUEEND + " REAL, " + + COLUMN_WEDSTART + " REAL, " + + COLUMN_WEDEND + " REAL, " + + COLUMN_THUSTART + " REAL, " + + COLUMN_THUEND + " REAL, " + + COLUMN_FRISTART + " REAL, " + + COLUMN_FRIEND + " REAL, " + + COLUMN_SATSTART + " REAL, " + + COLUMN_SATEND + " REAL, " + + COLUMN_SUNSTART + " REAL, " + + COLUMN_SUNEND + " REAL)"); + + db.execSQL("ALTER TABLE " + TABLE_LOGIN + " ADD COLUMN " + COLUMN_ADDRESS + " TEXT"); + db.execSQL("ALTER TABLE " + TABLE_LOGIN + " ADD COLUMN " + COLUMN_PHONE + " TEXT"); + db.execSQL("ALTER TABLE " + TABLE_LOGIN + " ADD COLUMN " + COLUMN_COMPANY + " TEXT"); + db.execSQL("ALTER TABLE " + TABLE_LOGIN + " ADD COLUMN " + COLUMN_LICENSED + " TEXT"); + case 3: + db.execSQL("ALTER TABLE " + TABLE_LOGIN + " ADD COLUMN " + COLUMN_DESCRIPTION + " TEXT"); + db.execSQL("ALTER TABLE " + TABLE_LOGIN + " ADD COLUMN " + COLUMN_SALT + " TEXT"); + case 4: + db.execSQL("ALTER TABLE " + TABLE_SERVICEPROVIDERS + " ADD COLUMN " + COLUMN_AVERAGERATING + " REAL DEFAULT 0"); + db.execSQL("ALTER TABLE " + TABLE_SERVICEPROVIDERS + " ADD COLUMN " + COLUMN_RATERS + " REAL DEFAULT 0"); + db.execSQL("ALTER TABLE " + TABLE_SERVICEPROVIDERS + " ADD COLUMN " + COLUMN_ACTIVE + " TEXT DEFAULT 'active'"); + db.execSQL("CREATE TABLE IF NOT EXISTS "+ TABLE_BOOKINGS + "(" + + COLUMN_BOOKINGSERVICEPROVIDER + " TEXT," + + COLUMN_BOOKINGHOMEOWNER + " TEXT," + + COLUMN_BOOKINGSERVICE + " TEXT, " + + COLUMN_BOOKINGYEAR + " REAL," + + COLUMN_BOOKINGMONTH + " REAL, " + + COLUMN_BOOKINGDATE + " REAL, " + + COLUMN_BOOKINGSTART + " REAL, " + + COLUMN_BOOKINGEND + " REAL, " + + COLUMN_BOOKINGSTATUS + " TEXT, " + + COLUMN_RATING + " REAL DEFAULT 0 " + + ")"); + case 5: + db.execSQL("ALTER TABLE " + TABLE_BOOKINGS + " ADD COLUMN " + COLUMN_COMMENT + " TEXT DEFAULT ''"); + case 6: + Cursor cursor = db.query(TABLE_LOGIN, new String[]{COLUMN_USERNAME, COLUMN_PASSWORD}, null, null, + null, null, null); + if (cursor.moveToFirst()){ + for (int i = 0; i 0){ + cursor.close(); + return false; + } + cursor.close(); + + //Put values of UserType into columns + ContentValues values = new ContentValues(); + values.put(COLUMN_USERNAME, userType.getUsername()); + values.put(COLUMN_PASSWORD, userType.getHash()); + values.put(COLUMN_FIRSTNAME, userType.getFirstname()); + values.put(COLUMN_LASTNAME, userType.getLastname()); + values.put(COLUMN_SALT, userType.getSalt()); + values.put(COLUMN_USERTYPE, userType.getClass().getSimpleName()); + + //special case for ServiceProvider + if (userType instanceof ServiceProvider){ + ServiceProvider serviceProvider = (ServiceProvider)userType; + + String address = serviceProvider.getAddress(); + if (address != null){ + values.put(COLUMN_ADDRESS, address); + } + + String phone = serviceProvider.getPhonenumber(); + if (phone != null){ + values.put(COLUMN_PHONE, phone); + } + + String company = serviceProvider.getCompanyname(); + if (company != null){ + values.put(COLUMN_COMPANY, company); + } + + String licensed = String.valueOf(serviceProvider.isLicensed()); + values.put(COLUMN_LICENSED, licensed); + + String description = serviceProvider.getDescription(); + if (description != null){ + values.put(COLUMN_DESCRIPTION, description); + } + + ContentValues contentValues = new ContentValues(); + int[] setToZero = new int[]{0,0,0,0}; + addAvailabilityToContentValues(contentValues, COLUMN_MONSTART, COLUMN_MONEND, setToZero); + addAvailabilityToContentValues(contentValues, COLUMN_TUESTART, COLUMN_TUEEND, setToZero); + addAvailabilityToContentValues(contentValues, COLUMN_WEDSTART, COLUMN_WEDEND, setToZero); + addAvailabilityToContentValues(contentValues, COLUMN_THUSTART, COLUMN_THUEND, setToZero); + addAvailabilityToContentValues(contentValues, COLUMN_FRISTART, COLUMN_FRIEND, setToZero); + addAvailabilityToContentValues(contentValues, COLUMN_SATSTART, COLUMN_SATEND, setToZero); + addAvailabilityToContentValues(contentValues, COLUMN_SUNSTART, COLUMN_SUNEND, setToZero); + contentValues.put(COLUMN_AVAILABILITYNAME, serviceProvider.getUsername()); + + writeDB.insert(TABLE_AVAILABILITY, null, contentValues); + + } + + writeDB.insert(TABLE_LOGIN, null, values); + + return true; + } + + + /** + * Looks in database for user with requested username, and returns an + * object of UserType corresponding to said user's role. + * Returns null if no such user found. + * + * @param username username to look up + * @return object representing user found + */ + public UserType findUserByUsername(String username){ + if (username == null) return null; + UserType usertype = null; + Cursor cursor = readDB.rawQuery("SELECT * FROM " + TABLE_LOGIN + + " WHERE " + COLUMN_USERNAME + " = ?", + new String[]{username}); + + if (cursor.moveToFirst()){ + String hash = cursor.getString(1); + String firstname = cursor.getString(2); + String lastname = cursor.getString(3); + String address = cursor.getString(5); + String phonenumber = cursor.getString(6); + String companyname = cursor.getString(7); + boolean licensed = Boolean.parseBoolean(cursor.getString(8)); + String description = cursor.getString(9); + String salt = cursor.getString(10); + if (cursor.getString(4) + .equals("Admin")){ + usertype = new Admin(hash, salt); + } else if (cursor.getString(4) + .equals("ServiceProvider")){ + ServiceProvider serviceProvider = new ServiceProvider(username, hash, salt, firstname, lastname, address, phonenumber, companyname, licensed, description); + getAllServicesProvidedByUser(serviceProvider); + getAvailabilities(serviceProvider); + usertype = serviceProvider; + } else { + usertype = new HomeOwner(username, hash, salt, firstname, lastname); + } + } + + cursor.close(); + return usertype; + } + + /** + * Updates user login information and name for user with requested username. + * Returns true if a user of said username was found and entry updated. + * Returns false if no user was found of said username. + * + * + * @param username username of entry to update + * @param password new password + * @param firstname new first name + * @param lastname new last name + * + * @return whether updating user information was successful + */ + public boolean updateUserInfo(String username, String password, String firstname, String lastname){ + return updateUserInfo(username, password, firstname, lastname, + null, null, null, null, null); + } + + + /** + * This method only needs to be called for service providers. Updates user login and + * profile information with requested username. Returns true if entry was found and updated. + * Returns false if nobody was found with said username. + * + * @param username username of entry to update + * @param password new password + * @param firstname new first name + * @param lastname new last name + * @param address new address + * @param phonenumber new phone number + * @param companyname new company name + * @param licensed licensing status + * @param description new description + * + * @return whether updating user information was successful + */ + public boolean updateUserInfo(String username, String password, String firstname, String lastname, + String address, String phonenumber, String companyname, Boolean licensed, + String description){ + if (username == null) return false; + + ContentValues values = new ContentValues(); + if (password != null && !password.equals("")) { + String salt = PasswordEncryption.generateSalt(); + values.put(COLUMN_SALT, salt); + + String hash = PasswordEncryption.encrypt(password, salt); + values.put(COLUMN_PASSWORD, hash); + } + if (firstname != null && !firstname.equals("")) values.put(COLUMN_FIRSTNAME, firstname); + if (lastname != null && !lastname.equals(""))values.put(COLUMN_LASTNAME, lastname); + if (address != null && !address.equals(""))values.put(COLUMN_ADDRESS, address); + if (phonenumber != null && !phonenumber.equals(""))values.put(COLUMN_PHONE, phonenumber); + if (companyname != null && !companyname.equals(""))values.put(COLUMN_COMPANY, companyname); + if (licensed != null) values.put(COLUMN_LICENSED, String.valueOf(licensed)); + if (description != null )values.put(COLUMN_DESCRIPTION, description); + + + return writeDB.update(TABLE_LOGIN, values, COLUMN_USERNAME+" = ?", + new String[]{username}) > 0; + } + + /** + * Looks in database for user with requested username, and deletes the corresponding + * entry. Returns true if a user was deleted, false otherwise. + * + * @param username username of entry to delete + * @return whether a user was deleted + */ + public boolean deleteUser(String username) { + if (username == null) return false; + + Cursor cursor = readDB.rawQuery("SELECT * FROM " + TABLE_LOGIN + + " WHERE " + COLUMN_USERNAME + " = ?", + new String[]{username}); + + if (!cursor.moveToFirst()) return false; + + boolean deleted; + if (cursor.getString(4).equals("ServiceProvider")) { + deleted = writeDB.delete(TABLE_LOGIN, COLUMN_USERNAME+" = ?", + new String[]{username}) > 0; + + if (deleted) { + writeDB.delete(TABLE_SERVICEPROVIDERS, COLUMN_SERVICEPROVIDERNAME + " = ?", + new String[]{username}); + writeDB.delete(TABLE_AVAILABILITY, COLUMN_AVAILABILITYNAME + " = ?", + new String[]{username}); + } + cursor.close(); + return deleted; + } else { + cursor.close(); + return writeDB.delete(TABLE_LOGIN, COLUMN_USERNAME+" = ?", + new String[]{username}) > 0; + } + } + + /** + * Returns a list of String arrays containing the username, first name, + * last name, and user type of every user in TABLE_LOGIN. + * + * @return list of arrays of [username, first name, last name, user type] + */ + public List getAllUsers(){ + return getAll("SELECT " + COLUMN_USERNAME + ", " + + COLUMN_FIRSTNAME + ", " + + COLUMN_LASTNAME + ", " + + COLUMN_USERTYPE + + " FROM "+TABLE_LOGIN); + } + + //methods for table of services + + /** + * Adds a service to the database. Returns false if service already + * exists in the database. + * Returns true if successful in adding service to database. + * + * @param service service to be added + * @return true if adding service was successful + */ + public boolean addService(Service service){ + if (service == null) return false; + //Check for duplicate username by querying services table + Cursor cursor = writeDB.query(TABLE_SERVICES, + new String[] {COLUMN_SERVICE}, + COLUMN_SERVICE + " = ?", + new String[]{service.getName().toLowerCase().trim()}, + null, null, null, + "1"); + //If cursor has 1+ elements in it, username already exists in table + if (cursor != null && cursor.getCount() > 0){ + cursor.close(); + return false; + } + cursor.close(); + + ContentValues values = new ContentValues(); + values.put(COLUMN_SERVICE, service.getName().toLowerCase().trim()); + values.put(COLUMN_RATE, service.getRate()); + writeDB.insert(TABLE_SERVICES, null, values); + return true; + } + + /** + * Looks in database for service with specified, and returns an + * object of Service if found. + * Returns null if no such service found. + * + * @param serviceName service to look up + * @return object representing service found + */ + public Service findService(String serviceName){ + if (serviceName == null) return null; + + Service service; + serviceName = serviceName.toLowerCase().trim(); + Cursor cursor = readDB.rawQuery("SELECT * FROM " + TABLE_SERVICES + + " WHERE " + COLUMN_SERVICE + " = ?", + new String[]{serviceName}); + + if (cursor.moveToFirst()){ + String servName = cursor.getString(0); + double rate = cursor.getDouble(1); + service = new Service(servName, rate); + } else { + service = null; + } + cursor.close(); + return service; + } + + /** + * Updates service rate using a Service object. + * Returns true if a service was found and entry updated. + * Returns false if no service was found. + * + * + * @param service service object containing updated values + * + * @return true if updating service information was successful + */ + public boolean updateService(Service service){ + if (service == null) return false; + ContentValues values = new ContentValues(); + values.put(COLUMN_RATE, service.getRate()); + + return writeDB.update(TABLE_SERVICES, values, COLUMN_SERVICE+" = ?", + new String[]{service.getName().toLowerCase().trim()}) > 0; + } + + /** + * Updates service rate using input of service name and rate. + * Returns true if a service was found and entry updated. + * Returns false if no service was found. + * + * + * @param name name of service + * @param rate rate of service + * + * @return true if updating service information was successful + */ + public boolean updateService(String name, double rate){ + if (name == null) return false; + + name = name.toLowerCase().trim(); + ContentValues values = new ContentValues(); + if (rate > 0) + values.put(COLUMN_RATE, rate); + + return writeDB.update(TABLE_SERVICES, values, COLUMN_SERVICE+" = ?", + new String[]{name}) > 0; + } + + /** + * Looks in database for a service, and deletes the corresponding + * entry. Returns true if a service was deleted, false otherwise. + * + * @param service service of entry to delete + * @return true if the service was deleted + */ + public boolean deleteService(String service) { + if (service == null) return false; + + boolean deleted; + String nullify = null; + service = service.toLowerCase().trim(); + + deleted = writeDB.delete(TABLE_SERVICES, COLUMN_SERVICE+" = ?", + new String[]{service}) > 0; + + if (deleted) { + writeDB.delete(TABLE_SERVICEPROVIDERS, COLUMN_SERVICEPROVIDERSERVICE + " = ?", + new String[]{service}); + } + return deleted; + } + + + /** + * Returns a list of String arrays containing the service categories, + * names and hourly rates. + * + * @return list of arrays of [service, rate] + */ + public List getAllServices(){ + return getAll("SELECT * FROM " + TABLE_SERVICES + " ORDER BY " + COLUMN_SERVICE); + } + + /** + * Adds a service to a service provider. The service provider now offers the service. + * + * @param serviceProvider service provider who offers service + * @param service service offered + * + * @return true if adding service to provider was successful + */ + public boolean addServiceProvidedByUser(ServiceProvider serviceProvider, Service service){ + if (serviceProvider == null || service == null) return false; + return addServiceProvidedByUser(serviceProvider.getUsername(), service.getName()); + } + + /** + * Adds a service to a service provider. The service provider now offers the service. + * + * @param serviceProvider service provider who offers service + * @param serviceName service offered + * + * @return true if adding service to provider was successful + */ + public boolean addServiceProvidedByUser(ServiceProvider serviceProvider, String serviceName){ + if (serviceProvider == null || serviceName == null) return false; + return addServiceProvidedByUser(serviceProvider.getUsername(), serviceName); + } + + /** + * Adds a service to a service provider. The service provider now offers the service. + * + * @param serviceProviderUsername service provider who offers service + * @param serviceName service offered + * + * @return true if adding service to provider was successful + */ + public boolean addServiceProvidedByUser(String serviceProviderUsername, String serviceName){ + if (serviceProviderUsername == null || serviceName == null) return false; + + //TODO: Check if serviceProviderUsername and serviceName are in db before adding + + serviceName = serviceName.toLowerCase().trim(); + + //Check for duplicate username/service combination by querying login table + Cursor cursor = writeDB.query(TABLE_SERVICEPROVIDERS, + new String[] {COLUMN_ACTIVE}, + COLUMN_SERVICEPROVIDERNAME + " = ? AND " + + COLUMN_SERVICEPROVIDERSERVICE + " = ?", + new String[]{serviceProviderUsername, serviceName}, + null, null, null, + "1"); + //If cursor has 1+ elements in it, username/service combination already exists in table + if (cursor.moveToFirst()){ + if (cursor.getString(0).equals("active")){ + cursor.close(); + return false; + } else { + ContentValues values = new ContentValues(); + values.put(COLUMN_ACTIVE, "active"); + return writeDB.update(TABLE_SERVICEPROVIDERS, values, + COLUMN_SERVICEPROVIDERNAME + " = ? AND " + + COLUMN_SERVICEPROVIDERSERVICE + " = ?", + new String[]{serviceProviderUsername, serviceName})>0; + } + + } + cursor.close(); + + ContentValues values = new ContentValues(); + values.put(COLUMN_SERVICEPROVIDERNAME, serviceProviderUsername); + values.put(COLUMN_SERVICEPROVIDERSERVICE, serviceName); + writeDB.insert(TABLE_SERVICEPROVIDERS, null, values); + return true; + } + + /** + * Removes service from service provider. Provider no longer offers this service. + * + * @param serviceProvider service provider who once offered service + * @param service service to be removed + * + * @return true if service provider's status for this service is now inactive + */ + public boolean deleteServiceProvidedByUser(ServiceProvider serviceProvider, Service service){ + if (serviceProvider == null || service == null) return false; + return deleteServiceProvidedByUser(serviceProvider.getUsername(), service.getName()); + } + + /** + * Removes service from service provider. Provider no longer offers this service. + * + * @param serviceProvider service provider who once offered service + * @param serviceName service to be removed + * + * @return true if service provider's status for this service is now inactive + */ + public boolean deleteServiceProvidedByUser(ServiceProvider serviceProvider, String serviceName){ + if (serviceProvider == null || serviceName == null) return false; + return deleteServiceProvidedByUser(serviceProvider.getUsername(), serviceName); + } + + /** + * Removes service from service provider. Provider no longer offers this service. + * + * @param serviceProviderUsername service provider who once offered service + * @param serviceName service to be removed + * + * @return true if service provider's status for this service is now inactive + */ + public boolean deleteServiceProvidedByUser(String serviceProviderUsername, String serviceName){ + if (serviceProviderUsername == null || serviceName == null) return false; + serviceName = serviceName.toLowerCase().trim(); + + ContentValues values = new ContentValues(); + values.put(COLUMN_ACTIVE, "inactive"); + + return writeDB.update(TABLE_SERVICEPROVIDERS, values, + COLUMN_SERVICEPROVIDERNAME + " = ? AND " + + COLUMN_SERVICEPROVIDERSERVICE + " = ?", + new String[]{serviceProviderUsername, serviceName}) > 0; + } + + /** + * Fetches all services provided by a service provider + * + * @param serviceProvider + * @return a list of [service, rate] + */ + public List getAllServicesProvidedByUser(ServiceProvider serviceProvider){ + if (serviceProvider == null) return new ArrayList<>(); + + return getAllServicesProvidedByUser(serviceProvider.getUsername()); + } + + /** + * Fetches all services provided by a service provider + * + * @param serviceProviderName + * @return a list of [service, rate] + */ + public List getAllServicesProvidedByUser(String serviceProviderName){ + if (serviceProviderName == null) return new ArrayList<>(); + + return getAll("SELECT " + TABLE_SERVICES + "." + COLUMN_SERVICE + ", " + + TABLE_SERVICES + "." + COLUMN_RATE + + " FROM " + TABLE_SERVICES + " JOIN " + TABLE_SERVICEPROVIDERS + + " ON " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERSERVICE + " = " + + TABLE_SERVICES + "." + COLUMN_SERVICE + + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + + "= '" + serviceProviderName + "'" + + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_ACTIVE + " = 'active'"); + } + + /** + * Fetches all service providers who provide a specified service + * + * @param service name of service + * @return a list of [username, first name, last name, average rating] sorted by rating + */ + public List getAllProvidersByService(Service service){ + if (service == null) return new ArrayList<>(); + + return getAllProvidersByService(service.getName()); + } + + /** + * Fetches all service providers who provide a specified service + * + * @param serviceName name of service + * @return a list of [username, first name, last name, average rating] sorted by rating + */ + public List getAllProvidersByService(String serviceName){ + if (serviceName == null) return new ArrayList<>(); + + serviceName = serviceName.toLowerCase().trim(); + return getAll( + "SELECT " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + ", " + + TABLE_LOGIN + "." + COLUMN_FIRSTNAME + ", " + + TABLE_LOGIN + "." + COLUMN_LASTNAME + ", " + + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + + " FROM " + TABLE_SERVICEPROVIDERS + " JOIN " + TABLE_LOGIN + + " ON " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + " = " + + TABLE_LOGIN + "." + COLUMN_USERNAME + + " AND " + COLUMN_SERVICEPROVIDERSERVICE + " = '" + serviceName + "'" + + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_ACTIVE + " = 'active'" + + " ORDER BY " + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + " DESC"); + } + + /** + * Updates a service provider's availabilities based on ServiceProvider object provided + * + * @param serviceProvider + * @return true if availability was updated successfully + */ + public boolean updateAvailability(ServiceProvider serviceProvider){ + //availability is stored as number of minutes from 00:00 + if (serviceProvider == null) return false; + int[][] availabilities = serviceProvider.getAvailabilities(); + if (availabilities == null) return false; + + Cursor cursor = readDB.rawQuery("SELECT * FROM " + TABLE_AVAILABILITY + + " WHERE " + COLUMN_AVAILABILITYNAME + " = ?", + new String[]{serviceProvider.getUsername()}); + + ContentValues contentValues = new ContentValues(); + addAvailabilityToContentValues(contentValues, COLUMN_MONSTART, COLUMN_MONEND, availabilities[0]); + addAvailabilityToContentValues(contentValues, COLUMN_TUESTART, COLUMN_TUEEND, availabilities[1]); + addAvailabilityToContentValues(contentValues, COLUMN_WEDSTART, COLUMN_WEDEND, availabilities[2]); + addAvailabilityToContentValues(contentValues, COLUMN_THUSTART, COLUMN_THUEND, availabilities[3]); + addAvailabilityToContentValues(contentValues, COLUMN_FRISTART, COLUMN_FRIEND, availabilities[4]); + addAvailabilityToContentValues(contentValues, COLUMN_SATSTART, COLUMN_SATEND, availabilities[5]); + addAvailabilityToContentValues(contentValues, COLUMN_SUNSTART, COLUMN_SUNEND, availabilities[6]); + + if (!cursor.moveToFirst()){ + contentValues.put(COLUMN_AVAILABILITYNAME, serviceProvider.getUsername()); + writeDB.insert(TABLE_AVAILABILITY, null, contentValues); + } else { + writeDB.update(TABLE_AVAILABILITY, contentValues, + COLUMN_AVAILABILITYNAME + " = ?", new String[]{serviceProvider.getUsername()}); + } + return true; + } + + + //note that this method overwrites serviceProvider's availability if it exists + public int[][] getAvailabilities(ServiceProvider serviceProvider){ + if (serviceProvider==null) return new int[7][4]; + Cursor cursor = readDB.rawQuery("SELECT * FROM " + TABLE_AVAILABILITY + + " WHERE " + COLUMN_AVAILABILITYNAME + " = ?", + new String[]{serviceProvider.getUsername()}); + if (cursor.moveToFirst()){ + for (int i = 0; i < 7; i++) { + int start = cursor.getInt(i*2+1); + int end = cursor.getInt(i*2+2); + serviceProvider.setAvailabilities(i, start/60, start%60, + end/60, end%60); + } + } else { + return new int[7][4]; + } + return serviceProvider.getAvailabilities(); + } + + public int[][] getAvailabilities(String serviceProviderName){ + int[][] availabilities = new int[7][4]; + if (serviceProviderName==null) return availabilities; + + Cursor cursor = readDB.rawQuery("SELECT * FROM " + TABLE_AVAILABILITY + + " WHERE " + COLUMN_AVAILABILITYNAME + " = ?", + new String[]{serviceProviderName}); + if (cursor.moveToFirst()){ + for (int i = 0; i < 7; i++) { + int start = cursor.getInt(i*2+1); + int end = cursor.getInt(i*2+2); + availabilities[i] = new int[]{start/60, start%60, end/60, end%60}; + } + } + return availabilities; + } + + + /** + * Returns a list of unbooked time slots that are at least 30 minutes + * @param serviceProvider + * @param year + * @param month + * @param day + * @return list of [start hour, start minute, end hour, end minute] of available timeslots + */ + public List getAvailabilityByDate(ServiceProvider serviceProvider, int year, int month, int day){ + return getAvailabilityByDate(serviceProvider.getUsername(), year, month, day); + } + + /** + * Returns a list of unbooked time slots that are at least 30 minutes + * @param serviceProvider + * @param year + * @param month + * @param day + * @return list of [start hour, start minute, end hour, end minute] of available timeslots + */ + public List getAvailabilityByDate(String serviceProvider, int year, int month, int day){ + + List availabilities = new ArrayList<>(); + + Cursor bookings = writeDB.query(TABLE_BOOKINGS, new String[] {COLUMN_BOOKINGSTART, COLUMN_BOOKINGEND}, + COLUMN_BOOKINGSERVICEPROVIDER+ " = ?" + + " AND " + COLUMN_BOOKINGYEAR + " = ?" + + " AND " + COLUMN_BOOKINGMONTH + " = ?" + + " AND " + COLUMN_BOOKINGDATE + " = ?", + new String[]{serviceProvider, String.valueOf(year), + String.valueOf(month),String.valueOf(day)}, + null, null, COLUMN_BOOKINGSTART, null); + + Cursor availability = getAvailabilityByDayOfWeek(serviceProvider, year, month, day); + if (availability.moveToFirst()) { + int previousEnd = availability.getInt(0); + int currentStart; + int currentEnd; + if (bookings.moveToFirst()) { + for (int i = 0; i < bookings.getCount(); i++) { + currentStart = bookings.getInt(0); + if (currentStart - previousEnd >= 30){ + availabilities.add(new int[]{previousEnd/60, previousEnd%60, + currentStart/60, currentStart%60}); + } + previousEnd = bookings.getInt(1); + bookings.moveToNext(); + } + currentStart = availability.getInt(1); + if (currentStart - previousEnd >= 30){ + availabilities.add(new int[]{previousEnd/60, previousEnd%60, + currentStart/60, currentStart%60}); + } + } else { + currentStart = availability.getInt(0); + currentEnd = availability.getInt(1); + availabilities.add(new int[]{currentStart/60, currentStart%60, + currentEnd/60, currentEnd%60}); + } + } + return availabilities; + } + + public boolean addBooking(Booking booking){ + if (booking == null) return false; + + return addBooking(booking.getServiceprovider().getUsername(), + booking.getHomeowner().getUsername(), booking.getService().getName(), + booking.getYear(), booking.getMonth(), booking.getDay(), + booking.getStarth(), booking.getStartmin(), + booking.getEndh(), booking.getEndmin()); + } + + public boolean addBooking(String serviceProvider, String homeOwner, String service, + String monthDayYear, int starth, int startmin, int endh, int endmin){ + String[] date = monthDayYear.split("/"); + + return addBooking(serviceProvider, homeOwner, service, + Integer.parseInt(date[2]), Integer.parseInt(date[0]), Integer.parseInt(date[1]), + starth, startmin, endh, endmin); + } + + /** + * + * @param serviceProvider + * @param homeOwner + * @param service + * @param year + * @param month + * @param day + * @param starth + * @param startmin + * @param endh + * @param endmin + * @return true if booking was successfully added + */ + public boolean addBooking(String serviceProvider, String homeOwner, String service, + int year, int month, int day, + int starth, int startmin, int endh, int endmin){ + + GregorianCalendar current = new GregorianCalendar(); + current.setTimeInMillis(System.currentTimeMillis()); + GregorianCalendar bookDate = new GregorianCalendar(year, month-1, day, starth, startmin); + + //check if time of booking is after this time + if (current.compareTo(bookDate) > 0) return false; + + service = service.trim().toLowerCase(); + + Cursor cursor = writeDB.query(TABLE_SERVICEPROVIDERS, new String[]{COLUMN_SERVICEPROVIDERNAME}, + COLUMN_SERVICEPROVIDERNAME + " = ? AND " + + COLUMN_SERVICEPROVIDERSERVICE + " = ?", + new String[] {serviceProvider, service}, + null, null, null, "1"); + if (!cursor.moveToFirst()) { + cursor.close(); + return false; + } + cursor.close(); + + if (isProviderAvailable(serviceProvider, year, month, day, starth, startmin, + endh, endmin)){ + + ContentValues contentValues = new ContentValues(); + contentValues.put(COLUMN_BOOKINGSTART, starth * 60 + startmin); + contentValues.put(COLUMN_BOOKINGEND, endh * 60 + endmin); + contentValues.put(COLUMN_BOOKINGDATE, day); + contentValues.put(COLUMN_BOOKINGMONTH, month); + contentValues.put(COLUMN_BOOKINGYEAR, year); + contentValues.put(COLUMN_BOOKINGSERVICEPROVIDER, serviceProvider); + contentValues.put(COLUMN_BOOKINGHOMEOWNER, homeOwner); + contentValues.put(COLUMN_BOOKINGSERVICE, service); + contentValues.put(COLUMN_BOOKINGSTATUS, Status.PENDING.toString()); + contentValues.put(COLUMN_RATING, 0); + + writeDB.insert(TABLE_BOOKINGS, null, contentValues); + + return true; + } + return false; + } + + /** + * + * @param username + * @return list of booking objects related to specified user. + * Returns an empty list if no bookings found + */ + public List findBookings(String username){ + ServiceProvider serviceProvider = null; + HomeOwner homeOwner = null; + Cursor cursor = writeDB.rawQuery("SELECT " + COLUMN_USERTYPE + " FROM " + TABLE_LOGIN + " WHERE " + + COLUMN_USERNAME + " = ?", + new String[] {username}); + if (!cursor.moveToFirst() || cursor.getString(0).equals("Admin")) return new ArrayList<>(); + + if (cursor.getString(0).equals("ServiceProvider")) { + serviceProvider = (ServiceProvider)findUserByUsername(username); + cursor = writeDB.rawQuery("SELECT * FROM " + TABLE_BOOKINGS + " WHERE " + + COLUMN_BOOKINGSERVICEPROVIDER + " = ?", + new String[]{username}); + } else { + homeOwner = (HomeOwner)findUserByUsername(username); + cursor = writeDB.rawQuery("SELECT * FROM " + TABLE_BOOKINGS + " WHERE " + + COLUMN_BOOKINGHOMEOWNER + " = ?", + new String[]{username}); + } + + return getBookings(cursor, serviceProvider, homeOwner); + } + + /** + * + * @param username + * @return list of booking objects related to specified user. + * Returns an empty list if no bookings found + */ + public List findNonCancelledBookings(String username) { + List bookingList = new ArrayList<>(); + ServiceProvider serviceProvider = null; + HomeOwner homeOwner = null; + Cursor cursor = writeDB.rawQuery("SELECT " + COLUMN_USERTYPE + " FROM " + TABLE_LOGIN + " WHERE " + + COLUMN_USERNAME + " = ?", + new String[]{username}); + if (!cursor.moveToFirst() || cursor.getString(0).equals("Admin")) return bookingList; + + if (cursor.getString(0).equals("ServiceProvider")) { + serviceProvider = (ServiceProvider) findUserByUsername(username); + cursor = writeDB.rawQuery("SELECT * FROM " + TABLE_BOOKINGS + " WHERE " + + COLUMN_BOOKINGSERVICEPROVIDER + " = ? AND " + + COLUMN_BOOKINGSTATUS + " != ?", + new String[]{username, Status.CANCELLED.toString()}); + } else { + homeOwner = (HomeOwner) findUserByUsername(username); + cursor = writeDB.rawQuery("SELECT * FROM " + TABLE_BOOKINGS + " WHERE " + + COLUMN_BOOKINGHOMEOWNER + " = ? AND " + + COLUMN_BOOKINGSTATUS + " != ?", + new String[]{username, Status.CANCELLED.toString()}); + } + + return getBookings(cursor, serviceProvider, homeOwner); + } + + /** + * Sets status of specified booking to cancelled. Returns false if booking + * does not exist in database, or date of booking has already passed. + * + * @param booking + * @return true if booking was successfully cancelled + */ + public boolean confirmBooking(Booking booking){ + return modifyBookingStatus(booking, Status.CONFIRMED); + } + + /** + * Sets status of specified booking to cancelled. Returns false if booking was already cancelled, + * booking does not exist in database, or date of booking has already passed. + * + * @param booking + * @return true if booking was successfully cancelled + */ + public boolean cancelBooking(Booking booking){ + return modifyBookingStatus(booking, Status.CANCELLED); + } + + /** + * Add a rating for a specific booking, and updates the average rating for the service provider + * and service combination. The booking must have passed before a rating can be added. + * Note that the rating is final. + * + * @param booking Booking with rating and comment already included + * @return true if adding the rating was successful + */ + public boolean addRating(Booking booking){ + return addRating(booking, booking.getRating(), booking.getComment()); + } + + /** + * Add a rating for a specific booking, and updates the average rating for the service provider + * and service combination. The booking must have passed before a rating can be added. + * Note that the rating is final. + * + * @param booking + * @param rating + * + * @return true if adding the rating was successful + */ + public boolean addRating(Booking booking, double rating){ + return addRating(booking, rating, ""); + } + + /** + * Add a rating for a specific booking, and updates the average rating for the service provider + * and service combination. The booking must have passed before a rating can be added. + * Note that the rating is final. + * + * @param booking + * @param rating + * @param comment + * @return true if adding the rating was successful + */ + public boolean addRating(Booking booking, double rating, String comment){ + if (booking == null) return false; + + GregorianCalendar current = new GregorianCalendar(); + current.setTimeInMillis(System.currentTimeMillis()); + GregorianCalendar bookDate = new GregorianCalendar(booking.getYear(), booking.getMonth()-1, + booking.getDay(), booking.getEndh(), booking.getEndmin()); + + //check if time of booking is before this time + if (current.compareTo(bookDate) < 0) return false; + + ContentValues contentValues = new ContentValues(); + contentValues.put(COLUMN_RATING, rating); + contentValues.put(COLUMN_COMMENT, comment); + + Cursor cursor = writeDB.query(TABLE_BOOKINGS, new String[]{COLUMN_RATING}, + COLUMN_BOOKINGSERVICEPROVIDER + " = ? AND " + + COLUMN_BOOKINGHOMEOWNER + " = ? AND " + + COLUMN_BOOKINGYEAR + " = ? AND " + + COLUMN_BOOKINGMONTH + " = ? AND " + + COLUMN_BOOKINGDATE + " = ? AND " + + COLUMN_BOOKINGSTART + " = ?", + new String[] {booking.getServiceprovider().getUsername(), + booking.getHomeowner().getUsername(), + String.valueOf(booking.getYear()), + String.valueOf(booking.getMonth()), + String.valueOf(booking.getDay()), + String.valueOf(booking.getStarth()*60 + booking.getStartmin())}, + null, null, null, null); + int previousrating = 0; + + if (cursor.moveToFirst()){ + previousrating = cursor.getInt(0); + } + + boolean updated = writeDB.update(TABLE_BOOKINGS, contentValues, + COLUMN_BOOKINGSERVICEPROVIDER + " = ? AND " + + COLUMN_BOOKINGHOMEOWNER + " = ? AND " + + COLUMN_BOOKINGYEAR + " = ? AND " + + COLUMN_BOOKINGMONTH + " = ? AND " + + COLUMN_BOOKINGDATE + " = ? AND " + + COLUMN_BOOKINGSTART + " = ? AND " + + COLUMN_BOOKINGSTART + " != ?", + new String[] {booking.getServiceprovider().getUsername(), + booking.getHomeowner().getUsername(), + String.valueOf(booking.getYear()), + String.valueOf(booking.getMonth()), + String.valueOf(booking.getDay()), + String.valueOf(booking.getStarth()*60 + booking.getStartmin()), + Status.CANCELLED.toString()}) > 0; + + if (updated) { + cursor = writeDB.query(TABLE_SERVICEPROVIDERS, new String[]{COLUMN_AVERAGERATING, COLUMN_RATERS}, + COLUMN_SERVICEPROVIDERNAME + " = ? AND " + + COLUMN_SERVICEPROVIDERSERVICE + " = ?", + new String[] {booking.getServiceprovider().getUsername(), booking.getService().getName().toLowerCase().trim()}, + null, null, null, null); + + cursor.moveToFirst(); + + int currentRaters = cursor.getInt(1); + double currentAverageRatings = cursor.getDouble(0)*currentRaters + + rating - previousrating; + currentRaters += previousrating == 0? 1 : 0; + cursor.close(); + + contentValues = new ContentValues(); + contentValues.put(COLUMN_AVERAGERATING, currentAverageRatings/(double)currentRaters); + contentValues.put(COLUMN_RATERS, currentRaters); + + writeDB.update(TABLE_SERVICEPROVIDERS, contentValues, + COLUMN_SERVICEPROVIDERNAME + " = ? AND " + + COLUMN_SERVICEPROVIDERSERVICE + " = ?", + new String[] {booking.getServiceprovider().getUsername(), + booking.getService().getName().toLowerCase().trim()}); + } + return updated; + + } + + /** + * Returns the average rating for a service provider's service + * + * @param serviceProvider + * @param service + * @return average rating of specified service provider and service combination + */ + public double getAverageRating(ServiceProvider serviceProvider, Service service){ + return getAverageRating(serviceProvider.getUsername(), service.getName()); + } + + /** + * Returns the average rating for a service provider's service + * + * @param serviceProviderName name of service provider + * @param serviceName name of service + * @return average rating of specified service provider and service combination + */ + public double getAverageRating(String serviceProviderName, String serviceName){ + serviceName = serviceName.trim().toLowerCase(); + Cursor cursor = writeDB.query(TABLE_SERVICEPROVIDERS, new String[]{COLUMN_AVERAGERATING}, + COLUMN_SERVICEPROVIDERNAME + " = ? AND " + + COLUMN_SERVICEPROVIDERSERVICE + " = ?", + new String[] {serviceProviderName, serviceName}, + null, null, null, null); + cursor.moveToFirst(); + double rating = cursor.getDouble(0); + cursor.close(); + + return rating; + } + + /** + * Gets a list of Strings in form [Homeowner username, rating, comment] for a specific + * service provider and service combination. Only includes bookings that have been rated. + * + * @param serviceProvider + * @param service + * @return + */ + public List getAllRatingsAndComments(ServiceProvider serviceProvider, Service service){ + return getAllRatingsAndComments(serviceProvider.getUsername(), service.getName()); + } + + /** + * Gets a list of Strings in form [Homeowner username, rating, comment] for a specific + * service provider and service combination. Only includes bookings that have been rated. + * + * @param serviceProviderName + * @param serviceName + * @return + */ + public List getAllRatingsAndComments(String serviceProviderName, String serviceName){ + serviceName = serviceName.toLowerCase().trim(); + return getAll("SELECT " + COLUMN_BOOKINGHOMEOWNER +", " + + COLUMN_RATING + ", " + COLUMN_COMMENT + " FROM " + TABLE_BOOKINGS + + " WHERE " + COLUMN_BOOKINGSERVICEPROVIDER + " = '" + serviceProviderName + + "' AND " + COLUMN_BOOKINGSERVICE + " = '" + serviceName + + "' AND " + COLUMN_RATING + " > 0"); + } + + public String[] getSpecificRatingAndComment(String serviceProviderName, String serviceName, + int year, int month, int day, int starth, int startmin){ + Cursor cursor = writeDB.query(TABLE_BOOKINGS, + new String[]{COLUMN_BOOKINGHOMEOWNER, COLUMN_RATING, COLUMN_COMMENT}, + COLUMN_BOOKINGSERVICEPROVIDER + " = ? AND " + + COLUMN_BOOKINGSERVICE + " = ? AND " + + COLUMN_BOOKINGYEAR + " = ? AND " + + COLUMN_BOOKINGMONTH + " = ? AND " + + COLUMN_BOOKINGDATE + " = ? AND " + + COLUMN_BOOKINGSTART + " = ? AND " + + COLUMN_RATING + " > 0", + new String[]{serviceProviderName, serviceName, String.valueOf(year), + String.valueOf(month), String.valueOf(day), String.valueOf(starth*60+startmin)}, + null, null, null, null); + if (cursor.moveToFirst()){ + return new String[]{cursor.getString(0), + cursor.getString(1),cursor.getString(2)}; + } else { + return null; + } + } + + /** + * Returns the number of people who rated a service provider's service + * + * @param serviceProvider name of service provider + * @param service name of service + * @return number of raters for specified service provider and service combination + */ + public int getRaters(ServiceProvider serviceProvider, Service service){ + return getRaters(serviceProvider.getUsername(), service.getName()); + + } + + /** + * Returns the number of people who rated a service provider's service + * + * @param serviceProviderName name of service provider + * @param serviceName name of service + * @return number of raters for specified service provider and service combination + */ + public int getRaters(String serviceProviderName, String serviceName){ + serviceName = serviceName.trim().toLowerCase(); + Cursor cursor = writeDB.query(TABLE_SERVICEPROVIDERS, new String[]{COLUMN_RATERS}, + COLUMN_SERVICEPROVIDERNAME + " = ? AND " + + COLUMN_SERVICEPROVIDERSERVICE + " = ?", + new String[] {serviceProviderName, serviceName}, + null, null, null, null); + cursor.moveToFirst(); + cursor.close(); + + return cursor.getInt(0); + } + + /** + * Returns list of [username, first name, last name, rating] of service providers that + * have a rating equal to or above the specified rating + * + * @param service + * @param rating minimum rating + * @return a List of [username, first name, last name, rating] of service providers + */ + public List getProvidersAboveRating(Service service, double rating){ + return getProvidersAboveRating(service.getName(), rating); + } + + /** + * Returns list of [username, first name, last name, rating] of service providers that + * have a rating equal to or above the specified rating + * + * @param serviceName name of service + * @param rating minimum rating + * @return a List of [username, first name, last name, rating] of service providers + */ + public List getProvidersAboveRating(String serviceName, double rating){ + serviceName = serviceName.trim().toLowerCase(); + return getAll("SELECT " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + ", " + + TABLE_LOGIN + "." + COLUMN_FIRSTNAME + ", " + + TABLE_LOGIN + "." + COLUMN_LASTNAME + ", " + + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + + " FROM " + TABLE_SERVICEPROVIDERS + " JOIN " + TABLE_LOGIN + + " ON " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + " = " + + TABLE_LOGIN + "." + COLUMN_USERNAME + + " AND " + COLUMN_SERVICEPROVIDERSERVICE + " = '" + serviceName + "'" + + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_ACTIVE + " = 'active'" + + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + " >= " + rating + + " ORDER BY " + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + " DESC"); + } + + /** + * Returns list of [username, first name, last name, rating] of service providers + * available at the specified time + * + * @param service + * @param year + * @param month + * @param day + * @param starth starting hour + * @param startmin starting minute + * @param endh ending hour + * @param endmin ending minute + * @return a List of [username, first name, last name, rating] of service providers + */ + public List getProvidersByTime(Service service, int year, int month, int day, + int starth, int startmin, int endh, int endmin){ + return getProvidersByTime(service.getName(), year, month, day, starth, startmin, endh, endmin); + } + + /** + * Returns list of [username, first name, last name, rating] of service providers + * available at the specified time + * + * @param serviceName name of service + * @param year + * @param month + * @param day + * @param starth starting hour + * @param startmin starting minute + * @param endh ending hour + * @param endmin ending minute + * @return a List of [username, first name, last name, rating] of service providers + */ + public List getProvidersByTime(String serviceName, int year, int month, int day, + int starth, int startmin, int endh, int endmin){ + serviceName = serviceName.trim().toLowerCase(); + List providers = getAll("SELECT " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + ", " + + TABLE_LOGIN + "." + COLUMN_FIRSTNAME + ", " + + TABLE_LOGIN + "." + COLUMN_LASTNAME + ", " + + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + + " FROM " + TABLE_SERVICEPROVIDERS + " JOIN " + TABLE_LOGIN + + " ON " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + " = " + + TABLE_LOGIN + "." + COLUMN_USERNAME + + " AND " + COLUMN_SERVICEPROVIDERSERVICE + " = '" + serviceName + "'" + + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_ACTIVE + " = 'active'" + + " ORDER BY " + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + " DESC"); + + for (int i = providers.size()-1; i >= 0; i--){ + if (!isProviderAvailable(providers.get(i)[0], year, month, day, + starth, startmin, endh, endmin)){ + providers.remove(i); + } + } + return providers; + } + + /** + * Returns list of [username, first name, last name, rating] of service providers + * available at the specified time and have a rating equal to or above the specified rating + * + * @param service + * @param rating minimum rating of filter + * @param year + * @param month + * @param day + * @param starth starting hour + * @param startmin starting minute + * @param endh ending hour + * @param endmin ending minute + * @return List of [username, first name, last name, rating] of service providers + */ + public List getProvidersByTimeAndRating(Service service, double rating, int year, int month, int day, + int starth, int startmin, int endh, int endmin){ + return getProvidersByTimeAndRating(service.getName(), rating, year, month, day, + starth, startmin, endh, endmin); + } + + /** + * Returns list of [username, first name, last name, rating] of service providers + * available at the specified time and have a rating equal to or above the specified rating. + * + * @param serviceName name of service + * @param rating minimum rating of filter + * @param year + * @param month + * @param day + * @param starth starting hour + * @param startmin starting minute + * @param endh ending hour + * @param endmin ending minute + * @return List of Strings of [username, first name, last name, rating] of service providers + */ + public List getProvidersByTimeAndRating(String serviceName, double rating, int year, int month, int day, + int starth, int startmin, int endh, int endmin){ + serviceName = serviceName.trim().toLowerCase(); + List providers = getProvidersByTime(serviceName, year, month, day, starth, startmin, endh, endmin); + + int i = providers.size()-1; + boolean allLowRatingsRemoved = false; + while (i>-1 && !allLowRatingsRemoved){ + if (getAverageRating(providers.get(i)[0], serviceName)>=rating){ + allLowRatingsRemoved = true; + } else { + providers.remove(i--); + } + } + return providers; + } + + + /** + * Prints all entries of table. One cell is printed per line with column name. + * Rows are separated by a blank line. + * + * @param tableName name of table to print + */ + void printTable(String tableName){ + Cursor cursor = readDB.rawQuery("SELECT * FROM "+tableName, null); + cursor.moveToFirst(); + for (int i = 0; i getAll(String rawQuery){ + List list = new LinkedList<>(); + String[] infoArray; + Cursor cursor = readDB.rawQuery(rawQuery,null); + + if (cursor.moveToFirst()) { + for (int i = 0; i < cursor.getCount(); i++) { + infoArray = new String[cursor.getColumnNames().length]; + for (int j = 0; j < cursor.getColumnNames().length; j++) { + infoArray[j] = cursor.getString(j); + } + list.add(infoArray); + cursor.moveToNext(); + } + } + cursor.close(); + return list; + } + + /** + * Adds a service provider's availabilities for a specific day to content values + * @param contentValues + * @param startColumn + * @param endColumn + * @param startAndEndTimes + */ + private void addAvailabilityToContentValues(ContentValues contentValues, + String startColumn, String endColumn, + int[] startAndEndTimes){ + if (startAndEndTimes == null){ + contentValues.put(startColumn, 0); + contentValues.put(endColumn, 0); + } else { + int startTime = startAndEndTimes[0]*60+startAndEndTimes[1]; + int endTime = startAndEndTimes[2]*60+startAndEndTimes[3]; + if (endTime - startTime <=0 || startTime > 1439 || startTime < 0 + || endTime > 1439 || endTime <= 0) { + contentValues.put(startColumn, 0); + contentValues.put(endColumn, 0); + } else { + contentValues.put(startColumn, startTime); + contentValues.put(endColumn, endTime); + } + } + + } + + /** + * Helper method to get a service provider's availability by day of week + * + * @param serviceProvider username of service provider + * @param year + * @param month + * @param day + * @return Cursor containing the start and end of the service provider's availabilities + * on selected day of the week + */ + private Cursor getAvailabilityByDayOfWeek(String serviceProvider, int year, int month, int day){ + GregorianCalendar start = new GregorianCalendar(year, month-1, day); + //Calendar.DAY_OF_WEEK starts with 1 for Sunday, and onwards + int dayOfWeek = start.get(Calendar.DAY_OF_WEEK); + Cursor cursor = null; + + //Check availabilities on day of week + switch (dayOfWeek){ + case 1: //Sunday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_SUNSTART, COLUMN_SUNEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + case 2: //Monday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_MONSTART, COLUMN_MONEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + case 3: //Tuesday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_TUESTART, COLUMN_TUEEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + case 4: //Wednesday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_WEDSTART, COLUMN_WEDEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + case 5: //Thursday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_THUSTART, COLUMN_THUEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + case 6: //Friday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_FRISTART, COLUMN_FRIEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + case 7: //Saturday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_SATSTART, COLUMN_SATEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + } + + return cursor; + } + + /** + * Helper method to change booking status + * @param booking + * @param status status to update + * @return true if modification was successful + */ + private boolean modifyBookingStatus(Booking booking, Status status){ + if (booking == null) return false; + + GregorianCalendar current = new GregorianCalendar(); + current.setTimeInMillis(System.currentTimeMillis()); + GregorianCalendar bookDate = new GregorianCalendar(booking.getYear(), booking.getMonth()-1, + booking.getDay(), booking.getStarth(), booking.getStartmin()); + + //check if time of booking has passed + if (current.compareTo(bookDate) > 0) return false; + + ContentValues contentValues = new ContentValues(); + contentValues.put(COLUMN_BOOKINGSTATUS, status.toString()); + + return writeDB.update(TABLE_BOOKINGS, contentValues, + COLUMN_BOOKINGSERVICEPROVIDER + " = ? AND " + + COLUMN_BOOKINGHOMEOWNER + " = ? AND " + + COLUMN_BOOKINGYEAR + " = ? AND " + + COLUMN_BOOKINGMONTH + " = ? AND " + + COLUMN_BOOKINGDATE + " = ? AND " + + COLUMN_BOOKINGSTART + " = ? AND " + + COLUMN_BOOKINGSTATUS + " != ?", + new String[] {booking.getServiceprovider().getUsername(), + booking.getHomeowner().getUsername(), + String.valueOf(booking.getYear()), + String.valueOf(booking.getMonth()), + String.valueOf(booking.getDay()), + String.valueOf(booking.getStarth()*60 + booking.getStartmin()), + Status.CANCELLED.toString()}) > 0; + } + + /** + * Helper method to determine whether service provider is available at specified date and time. + * Returns false if end time before start time, or service provider not available + * + * @param serviceProvider + * @param year + * @param month + * @param day + * @param starth + * @param startmin + * @param endh + * @param endmin + * @return true if service provider is available for specified time slot + */ + private boolean isProviderAvailable(String serviceProvider, int year, int month, int day, + int starth, int startmin, int endh, int endmin){ + + int bookingStart = starth*60 + startmin; + int bookingEnd = endh*60 + endmin; + int availabilityStart, availabilityEnd; + + if (bookingEnd < bookingStart) return false; + + Cursor cursor = getAvailabilityByDayOfWeek(serviceProvider, year, month, day); + + cursor.moveToFirst(); + availabilityStart = cursor.getInt(0); + availabilityEnd = cursor.getInt(1); + + //service provider not available if availability end is 0, if availability starts after booking start, + // or if availability ends before booking end + if (availabilityEnd == 0 || availabilityStart > bookingStart || availabilityEnd < bookingEnd) { + return false; + } + + //now we know for sure that the service provider is available on said day of the week + //we check to see if any of the bookings overlap on this time slot + cursor = writeDB.query(TABLE_BOOKINGS, new String[] {COLUMN_BOOKINGSTART, COLUMN_BOOKINGEND}, + COLUMN_BOOKINGSERVICEPROVIDER + " = ? AND " + + COLUMN_BOOKINGYEAR + " = ? AND " + + COLUMN_BOOKINGMONTH + " = ? AND " + + COLUMN_BOOKINGDATE + " = ? AND " + + COLUMN_BOOKINGSTATUS + " != ?", + new String[] {serviceProvider, String.valueOf(year), + String.valueOf(month), String.valueOf(day), Status.CANCELLED.toString()}, + null, null, COLUMN_BOOKINGSTART, null); + if (cursor.moveToFirst()){ + for (int i = 0; i= bookingStart)|| + (availabilityStart <= bookingEnd && availabilityEnd >= bookingEnd) || + (availabilityStart >= bookingStart && availabilityEnd <= bookingEnd)) return false; + + cursor.moveToNext(); + } + } + return true; + } + + private List getBookings(Cursor cursor, ServiceProvider serviceProvider, HomeOwner homeOwner){ + List bookingList = new ArrayList<>(); + + if (cursor.moveToFirst()) { + for (int i = 0; i < cursor.getCount(); i++) { + int startTime = cursor.getInt(6); + int endTime = cursor.getInt(7); + int starth = startTime / 60; + int startmin = startTime % 60; + int endh = endTime / 60; + int endmin = endTime % 60; + int day = cursor.getInt(5); + int month = cursor.getInt(4); + int year = cursor.getInt(3); + String stat = cursor.getString(8); + Status status = (stat.equals("Pending") ? Status.PENDING : + stat.equals("Confirmed") ? Status.CONFIRMED : Status.CANCELLED); + ServiceProvider serviceprovider = (serviceProvider == null ? + (ServiceProvider) findUserByUsername(cursor.getString(0)) : serviceProvider); + HomeOwner homeowner = (homeOwner == null ? + (HomeOwner) findUserByUsername(cursor.getString(1)) : homeOwner); + Service service = (Service)findService(cursor.getString(2)); + Booking booking = new Booking(starth, startmin, endh, endmin, day, month, year, + serviceprovider, homeowner, service); + booking.setStatus(status); + bookingList.add(booking); + + cursor.moveToNext(); + } + } + return bookingList; + } + +} + diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DeleteServiceDialogFragment.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DeleteServiceDialogFragment.java new file mode 100644 index 0000000..031cfae --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DeleteServiceDialogFragment.java @@ -0,0 +1,64 @@ +package com.uottawa.olympus.olympusservices; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.view.LayoutInflater; +import android.widget.EditText; +import android.widget.Toast; + +public class DeleteServiceDialogFragment extends DialogFragment{ + public interface NoticeDialogListener { + public void onDialogDelete(DialogFragment dialog); + public void onDialogNevermind(DialogFragment dialog); + } + DeleteServiceDialogFragment.NoticeDialogListener mListener; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + // Verify that the host activity implements the callback interface + try { + // Instantiate the NoticeDialogListener so we can send events to the host + mListener = (DeleteServiceDialogFragment.NoticeDialogListener) context; + } catch (ClassCastException e) { + // The activity doesn't implement the interface, throw exception + throw new ClassCastException(this.toString() + + " must implement NoticeDialogListener"); + } + } + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + // Get the layout inflater + LayoutInflater inflater = getActivity().getLayoutInflater(); + + // Inflate and set the layout for the dialog + // Pass null as the parent view because its going in the dialog layout + builder.setView(inflater.inflate(R.layout.dialog_service_delete, null)) + // Add action buttons + .setPositiveButton(R.string.remove, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + Bundle args = new Bundle(); + args.putString("name", (String)getArguments().get("name")); + DeleteServiceDialogFragment.this.setArguments(args); + mListener.onDialogDelete(DeleteServiceDialogFragment.this); + + + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + Bundle args = new Bundle(); + args.putString("name", (String)getArguments().get("name")); + mListener.onDialogNevermind(DeleteServiceDialogFragment.this); + } + }) + .setTitle((String)getArguments().get("name")); + return builder.create(); + } +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/EditServiceDialogFragment.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/EditServiceDialogFragment.java new file mode 100644 index 0000000..722a410 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/EditServiceDialogFragment.java @@ -0,0 +1,90 @@ +package com.uottawa.olympus.olympusservices; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.view.LayoutInflater; +import android.widget.EditText; +import android.widget.Toast; + +public class EditServiceDialogFragment extends DialogFragment{ + + /** + * Creates a NoticeDialogListener interface for other classes to + * implement to have this class be functional in the other classes. + * + */ + public interface NoticeDialogListener { + public void onDialogEdit(DialogFragment dialog); + public void onDialogDelete(DialogFragment dialog); + } + EditServiceDialogFragment.NoticeDialogListener mListener; + + // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener + @Override + public void onAttach(Context context) { + super.onAttach(context); + // Verify that the host activity implements the callback interface + try { + // Instantiate the NoticeDialogListener so we can send events to the host + mListener = (EditServiceDialogFragment.NoticeDialogListener) context; + } catch (ClassCastException e) { + // The activity doesn't implement the interface, throw exception + throw new ClassCastException(this.toString() + + " must implement NoticeDialogListener"); + } + } + + /** + * Edit the Dialog to change rate of a service that the + * admin wants to change. + * + * @param savedInstanceState Bundle to transfer information. + * @return Dialog that is sent to admin for information. + */ + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + // Get the layout inflater + LayoutInflater inflater = getActivity().getLayoutInflater(); + + // Inflate and set the layout for the dialog + // Pass null as the parent view because its going in the dialog layout + builder.setView(inflater.inflate(R.layout.dialog_service_edit, null)) + // Add action buttons + .setPositiveButton(R.string.update, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + Bundle args = new Bundle(); + args.putString("name", (String)getArguments().get("name")); + EditText rateInput = (EditText) ((AlertDialog) dialog).findViewById(R.id.RateInput); + if(rateInput.getText().toString().length()>0 && !rateInput.getText().toString().equals(".")){ + Double rate = Double.parseDouble(rateInput.getText().toString()); + args.putDouble("rate", rate); + + EditServiceDialogFragment.this.setArguments(args); + mListener.onDialogEdit(EditServiceDialogFragment.this); + } + else{ + Toast.makeText(getContext(), "Rate cannot be empty", Toast.LENGTH_LONG).show(); + + } + + } + }) + .setNegativeButton(R.string.delete, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + Bundle args = new Bundle(); + args.putString("name", (String)getArguments().get("name")); + + EditServiceDialogFragment.this.setArguments(args); + mListener.onDialogDelete(EditServiceDialogFragment.this); + } + }) + .setTitle((String)getArguments().get("name")); + return builder.create(); + } +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/FindServiceProvider.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/FindServiceProvider.java new file mode 100644 index 0000000..74a7d6d --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/FindServiceProvider.java @@ -0,0 +1,455 @@ +package com.uottawa.olympus.olympusservices; + +import android.app.DatePickerDialog; +import android.app.TimePickerDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.support.annotation.NonNull; +import android.support.design.widget.Snackbar; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.DatePicker; +import android.widget.ListView; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.RatingBar; +import android.widget.TextView; +import android.widget.TimePicker; +import android.widget.Toast; + +import com.jaredrummler.materialspinner.MaterialSpinner; + +import java.util.Calendar; +import java.util.Iterator; +import java.util.List; + +public class FindServiceProvider extends AppCompatActivity { + String username; + DBHelper dbHelper; + + //field for RecyclerView + private RecyclerView mRecyclerView; + //field for adapter of Recycler view + private RecyclerView.Adapter mAdapter; + //field for layout manager of Recyler view. + private RecyclerView.LayoutManager mLayoutManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_find_service_provider); + Bundle bundle = getIntent().getExtras(); + username = bundle.getString("username"); + + + dbHelper = new DBHelper(this); + MaterialSpinner spinner2 = findViewById(R.id.ServicesInput); + + List serviceslist = dbHelper.getAllServices(); + String[] services = new String[(serviceslist.size())]; + Iterator iter = serviceslist.iterator(); + for (int i=0; i providers; + if(!button.getText().toString().equals("Start") && !button2.getText().toString().equals("End") + && !button3.getText().toString().equals("Date")){ + System.out.println(button.getText().toString()+":"+button2.getText().toString()+":"+button3.getText().toString()); + start = button.getText().toString(); + end = button2.getText().toString(); + date = button3.getText().toString(); + + String[] dates = date.split("/"); + int month = Integer.parseInt(dates[0].replaceAll("\\s+","")); + int day = Integer.parseInt(dates[1].replaceAll("\\s+","")); + int year = Integer.parseInt(dates[2].replaceAll("\\s+","")); + + String[] starttimes = start.split(":"); + int starth = Integer.parseInt(starttimes[0].replaceAll("\\s+","")); + int startmin = Integer.parseInt(starttimes[1].replaceAll("\\s+","")); + + String[] endtimes = end.split(":"); + int endh = Integer.parseInt(endtimes[0].replaceAll("\\s+","")); + int endmin = Integer.parseInt(endtimes[1].replaceAll("\\s+","")); + + int[] times = {starth, startmin, endh, endmin}; + if(selectedId!=-1 && validateTime(times)){ + ratingpicked = (RadioButton) findViewById(selectedId); + rating = Double.parseDouble(ratingpicked.getText().toString()); + providers = dbHelper.getProvidersByTimeAndRating(service, rating, year, month, day, + starth, startmin, endh, endmin); + } + else if(validateTime(times)){ + providers = dbHelper.getProvidersByTime(service, year, month, day, + starth, startmin, endh, endmin); + } + else if(selectedId!=-1){ + Toast.makeText(this, "Times are invalid, only searching by service and rating"+starth+";"+startmin+","+endh+";"+endmin, Toast.LENGTH_SHORT).show(); + ratingpicked = (RadioButton) findViewById(selectedId); + rating = Double.parseDouble(ratingpicked.getText().toString()); + providers = dbHelper.getProvidersAboveRating(service, rating); + + } + else{ + Toast.makeText(this, "Times are invalid, only searching by service", Toast.LENGTH_SHORT).show(); + providers = dbHelper.getAllProvidersByService(service); + + } + } + else{ + if(selectedId!=-1){ + ratingpicked = (RadioButton) findViewById(selectedId); + rating = Double.parseDouble(ratingpicked.getText().toString()); + providers = dbHelper.getProvidersAboveRating(service, rating); + } + else{ + providers = dbHelper.getAllProvidersByService(service); + } + } + + //update recycler view + String[][] providerslist = new String[providers.size()][]; + for(int i=0; itime[0]){ + return true; + }else{ + if(time[2]==time[0]&&time[3]>time[1]){ + return true; + }else{ + return false; + } + } + } + + + public class MyAdapter extends RecyclerView.Adapter { + + private String[][] serviceProviders; + private Context context; + + // Provide a reference to the views for each data item + // Complex data items may need more than one view per item, and + // you provide access to all the views for a data item in a view holder + + // Provide a suitable constructor (depends on the kind of dataset) + public MyAdapter(String[][] serviceProviders, Context context) { + this.serviceProviders = serviceProviders; + } + + // Create new views (invoked by the layout manager) + @NonNull + @Override + public ProviderHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.service_list_item, parent, false); + ProviderHolder vh = new ProviderHolder(v); + return vh; + } + + // Replace the contents of a view (invoked by the layout manager) + @Override + public void onBindViewHolder(ProviderHolder holder, int position) { + String[] serviceprovider = serviceProviders[position]; + holder.name.setText(serviceprovider[1]+" "+serviceprovider[2]); + holder.rate.setText(""+serviceprovider[3]); + holder.username.setText(serviceprovider[0]); + + } + + // Return the size of your dataset (invoked by the layout manager) + @Override + public int getItemCount() { + return serviceProviders.length; + } + + class ProviderHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ + + TextView name; + TextView rate; + TextView username; + + public ProviderHolder(View row){ + super(row); + name = row.findViewById(R.id.Name); + rate = row.findViewById(R.id.Rate); + username = row.findViewById(R.id.Username); + row.setOnClickListener(this); + } + @Override + public void onClick(View view) { + TextView nameview = (TextView)view.findViewById(R.id.Username); + final String name = nameview.getText().toString(); + + AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(FindServiceProvider.this); + + + alertDialogBuilder.setView(R.layout.sp_info_item); + + + alertDialogBuilder.setPositiveButton("Make Booking", + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface arg0, int arg1) { + makeBooking(name); + } + }); + + alertDialogBuilder.setNegativeButton("Nevermind", + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + }); + + AlertDialog alertDialog = alertDialogBuilder.create(); + alertDialog.show(); + ServiceProvider sp = (ServiceProvider)dbHelper.findUserByUsername(name); + TextView spname = alertDialog.findViewById(R.id.NameName); + spname.setText(sp.getFirstname()+" "+sp.getLastname()); + + TextView company = alertDialog.findViewById(R.id.CompanyName); + company.setText(sp.getCompanyname()); + + TextView address = alertDialog.findViewById(R.id.AddressName); + address.setText(sp.getAddress()); + + TextView phone = alertDialog.findViewById(R.id.PhoneNumberName); + phone.setText(sp.getPhonenumber()); + + TextView licensed = alertDialog.findViewById(R.id.LicensedName); + if(sp.isLicensed()){ + licensed.setText("Yes"); + } + else{ + licensed.setText("No"); + } + TextView description = alertDialog.findViewById(R.id.DescriptionName); + description.setText(sp.getDescription()); + + TextView rating = alertDialog.findViewById(R.id.AverageRatingName); + MaterialSpinner spinner = findViewById(R.id.ServicesInput); + rating.setText(""+dbHelper.getAverageRating(name, spinner.getText().toString())); + + TextView ratingtext = alertDialog.findViewById(R.id.AverageRating); + ratingtext.setText("Rating for " +spinner.getText().toString()); + + //actual data + List randc = dbHelper.getAllRatingsAndComments(name,spinner.getText().toString()); + String[] ratings = new String[randc.size()]; + for(int i=0; i(FindServiceProvider.this, R.layout.simple_list_item_1_customized, ratings); + + ListView listView = (ListView) alertDialog.findViewById(R.id.RatingList); + listView.setAdapter(adapter); + + + + + } + + + } + + + } +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/HomeOwner.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/HomeOwner.java new file mode 100644 index 0000000..3b77303 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/HomeOwner.java @@ -0,0 +1,50 @@ +package com.uottawa.olympus.olympusservices; + + +/** + * The class HomeOwner is a child of the class userType. The class permission + * to the user of a standard homeowner hence users with homeowner permissions + * are able to book service providers. Has not been implemented yet. + * + */ + +public class HomeOwner extends UserType { + + /** + * Constructor of the HomeOwner object that takes the username, password, + * lastname, and firstname as parameters to use for the creation of a + * HomeOwner object. + * + * @param username String for username. + * @param password String for password. + * @param firstname String for firstname. + * @param lastname String for lastname. + */ + HomeOwner(String username, String password, String firstname, String lastname){ + super(username, password, firstname, lastname); + } + + /** + * Constructor of the HomeOwner object that takes the username, password, + * lastname, and firstname as parameters to use for the creation of a + * HomeOwner object. + * + * @param username String for username. + * @param hash String for hash. + * @param salt String for salt. + * @param firstname String for firstname. + * @param lastname String for lastname. + */ + HomeOwner(String username, String hash, String salt, String firstname, String lastname){ + super(username, hash, salt, firstname, lastname); + } + + /** + * Returns the type of role the user is for this class. + * will return the string "HomeOwner". + * + * @return "HomeOwner" String object. + */ + public String getRole(){ return "HomeOwner"; } + +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/HomeOwnerEditProfile.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/HomeOwnerEditProfile.java new file mode 100644 index 0000000..09741d6 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/HomeOwnerEditProfile.java @@ -0,0 +1,83 @@ +package com.uottawa.olympus.olympusservices; + +import android.content.Intent; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; +import android.widget.CheckBox; +import android.widget.TextView; +import android.widget.Toast; + +public class HomeOwnerEditProfile extends AppCompatActivity { + String username; + DBHelper dbHelper; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_home_owner_edit_profile); + + Bundle bundle = getIntent().getExtras(); + username = bundle.getString("username"); + dbHelper = new DBHelper(this); + UserType user; + user = dbHelper.findUserByUsername(username); + TextView firstname = findViewById(R.id.FirstNameInput); + TextView lastname = findViewById(R.id.LastNameInput); + TextView password = findViewById(R.id.PasswordInput); + + + firstname.setText(user.getFirstname()); + lastname.setText(user.getLastname()); + password.setText(""); + + } + /** + * Override so that previous screen refreshes when pressing the + * back button on this activity of the app. + * + */ + @Override + public void onBackPressed(){ + Intent intent = new Intent(getApplicationContext(),Welcome.class); + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + + + /** + * Saves updated user information to the database + * @param view + */ + public void Save(View view){ + TextView firstname = findViewById(R.id.FirstNameInput); + TextView lastname = findViewById(R.id.LastNameInput); + TextView password = findViewById(R.id.PasswordInput); + + //Checks for the fields + if((password.getText().toString().length()>=5 || password.getText().toString().equals("")) + && firstname.getText().toString().length()>0 + && lastname.getText().toString().length()>0 + && password.getText().toString().matches("[a-zA-Z0-9]*") + && firstname.getText().toString().matches("[a-zA-Z]*") + && lastname.getText().toString().matches("[a-zA-Z]*") + ) { + + if(dbHelper.updateUserInfo(username, password.getText().toString(), firstname.getText().toString(), lastname.getText().toString() + )){ + //add comment method here + Toast.makeText(this, "Profile has been updated", Toast.LENGTH_LONG).show(); + } + else{ + Toast.makeText(this, "Could not update profile ", Toast.LENGTH_LONG).show(); + + } + + } + else{ + Toast.makeText(this, "Fields cannot be empty and must be formatted correctly", Toast.LENGTH_LONG).show(); + } + } + +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/LogIn.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/LogIn.java index 02ed1f3..76688e1 100644 --- a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/LogIn.java +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/LogIn.java @@ -2,12 +2,99 @@ package com.uottawa.olympus.olympusservices; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; +import android.content.Intent; +import android.widget.EditText; +import android.view.View; +import android.widget.Toast; + +/** + * The login activity for the app that checks + * credentials of users to allow them to log in and use + * the functionality of the app. + * + */ public class LogIn extends AppCompatActivity { + /** + * On creation of this activity the login xml file + * is loaded up. + * + * @param savedInstanceState Bundle object for transfer of information. + */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_log_in); } + + /** + * On click of the login button the app checks if all specification + * for login credentials are met and then either sends an error toast + * or logs the user in. + * + * @param view View object that contains all the buttons and editTexts. + */ + public void onClickLogIn(View view){ + String username = ((EditText) findViewById(R.id.UsernameInput)).getText().toString(); + String password = ((EditText) findViewById(R.id.PasswordInput)).getText().toString(); + DBHelper dbHelper = new DBHelper(this); + if(username.matches("[a-zA-Z0-9]*")&&password.matches("[a-zA-Z0-9]*") + && password.length()>0 && username.length()>0) { + if (dbHelper.findUserByUsername(username) != null) { + UserType user = dbHelper.findUserByUsername(username); + if (user.getUsername().equals(username) && + PasswordEncryption.slowEquals(user.getHash(), + PasswordEncryption.encrypt(password, user.getSalt()))) { + if(user.getRole()=="Admin"){ + Intent intent = new Intent(getApplicationContext(),AdminWelcome.class); + startActivity(intent); + finish(); + } + else if(user.getRole()=="ServiceProvider"){ + Intent intent = new Intent(getApplicationContext(),ServiceProviderWelcome.class); + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + else { + Intent intent = new Intent(getApplicationContext(),Welcome.class); + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + + + } else { + Toast.makeText(this, "Wrong Password", Toast.LENGTH_LONG).show(); + } + } else { + Toast.makeText(this, "Account does not exist", Toast.LENGTH_LONG).show(); + } + } + else if(username.length()==0 || password.length()==0){ + Toast.makeText(this, "Fields cannot be empty", Toast.LENGTH_LONG).show(); + } + else{ + Toast.makeText(this, "Fields may only contain alphanumeric values", Toast.LENGTH_LONG).show(); + } + + + } + + /** + * app closes the the activity when back is pressed and + * no user information written down is saved in the EditText for + * security purposes. + */ + @Override + public void onBackPressed(){ + Intent intent = new Intent(getApplicationContext(), Main.class); + startActivity(intent); + finish(); + } + + + + } diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Main.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Main.java index f5722d9..eb86354 100644 --- a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Main.java +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Main.java @@ -5,13 +5,53 @@ import android.os.Bundle; import android.content.Intent; import android.view.View; +/** + * The starting page of the app which contains two buttons + * of either registering for the app or logging into an existing + * account. + * + */ + public class Main extends AppCompatActivity { + /** + * On creation of the object the app loads up the xml page + * for the class and creates dbHelper object and Admin object + * and then add the admin into the database. + * @param savedInstanceState + */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + UserType admin = new Admin(); + DBHelper dbHelper = new DBHelper(this); + dbHelper.addUser(admin); + } -} + /** + * On click of the sign up button loads up the sign up activity + * + * @param view View object containing the buttons. + */ + public void onClickSignUp(View view){ + Intent intent = new Intent(getApplicationContext(),SignUp.class); + startActivity(intent); + finish(); + + } + + /** + * On click of the Login button loads up the login activity. + * + * @param view View object containing the buttons. + */ + public void onClickLogIn(View view){ + Intent intent = new Intent(getApplicationContext(),LogIn.class); + startActivity(intent); + finish(); + } + +} \ No newline at end of file diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/MakeBooking.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/MakeBooking.java new file mode 100644 index 0000000..0b113dc --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/MakeBooking.java @@ -0,0 +1,227 @@ +package com.uottawa.olympus.olympusservices; + +import android.app.DatePickerDialog; +import android.app.TimePickerDialog; +import android.content.Intent; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.DatePicker; +import android.widget.TextView; +import android.widget.TimePicker; +import android.widget.Toast; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +public class MakeBooking extends AppCompatActivity { + String homeowner; + String serviceprovider; + String service; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_make_booking); + Bundle bundle = getIntent().getExtras(); + homeowner = bundle.getString("homeowner"); + serviceprovider = bundle.getString("serviceprovider"); + service = bundle.getString("service"); + + TextView homeo = findViewById(R.id.HomeOwner); + TextView servicep = findViewById(R.id.ServiceProvider); + TextView serv = findViewById(R.id.Service); + + homeo.setText("Home Owner: \n"+homeowner); + servicep.setText("ServiceProvider: \n"+serviceprovider); + serv.setText("Service: \n"+service); + + } + + @Override + public void onBackPressed(){ + Intent intent = new Intent(getApplicationContext(),Welcome.class); + intent.putExtra("username", homeowner); + startActivity(intent); + finish(); + } + public void Cancel(View view){ + onBackPressed(); + } + + public void Book(View view){ + Button button = findViewById(R.id.Start); + Button button2 = findViewById(R.id.End); + Button button3 = findViewById(R.id.Date); + + if(!button.getText().toString().equals("Start") && !button2.getText().toString().equals("End") + && !button3.getText().toString().equals("Date")){ + String[] dates = button3.getText().toString().split("/"); + int month = Integer.parseInt(dates[0].replaceAll("\\s+","")); + int day = Integer.parseInt(dates[1].replaceAll("\\s+","")); + int year = Integer.parseInt(dates[2].replaceAll("\\s+","")); + + String[] starttimes = button.getText().toString().split(":"); + int starth = Integer.parseInt(starttimes[0].replaceAll("\\s+","")); + int startmin = Integer.parseInt(starttimes[1].replaceAll("\\s+","")); + + String[] endtimes = button2.getText().toString().split(":"); + int endh = Integer.parseInt(endtimes[0].replaceAll("\\s+","")); + int endmin = Integer.parseInt(endtimes[1].replaceAll("\\s+","")); + + Date date = new Date(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + try { + Date selecteddate = sdf.parse(dates[2].replaceAll("\\s+","") + "-" + dates[0].replaceAll("\\s+","") + "-" + dates[1].replaceAll("\\s+","")); + if(selecteddate.compareTo(date)<0){ + Toast.makeText(this, "Date must be a future date", Toast.LENGTH_SHORT).show(); + } + else{ + if (starthtime[0]){ + return true; + }else{ + if(time[2]==time[0]&&time[3]>time[1]){ + return true; + }else{ + return false; + } + } + } + + +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/NewServiceDialogFragment.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/NewServiceDialogFragment.java new file mode 100644 index 0000000..09cc543 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/NewServiceDialogFragment.java @@ -0,0 +1,106 @@ +package com.uottawa.olympus.olympusservices; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.view.LayoutInflater; + +import android.content.res.Resources; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.ViewGroup; +import android.widget.EditText; +import android.view.View; +import android.widget.Toast; + +import com.rengwuxian.materialedittext.MaterialEditText; + +/** + * Creates a dialog whenever admin adds a new service into the + * service list which the admin fills in to provide the fields of + * the service. + */ +public class NewServiceDialogFragment extends DialogFragment { + + /** + * Creates a NoticeDialogListener interface for other classes to + * implement to have this class be functional in the other classes. + * + */ + public interface NoticeDialogListener { + public void onDialogNew(DialogFragment dialog); + public void onDialogNevermind(DialogFragment dialog); + } + NoticeDialogListener mListener; + + // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener + @Override + public void onAttach(Context context) { + super.onAttach(context); + // Verify that the host activity implements the callback interface + try { + // Instantiate the NoticeDialogListener so we can send events to the host + mListener = (NoticeDialogListener) context; + } catch (ClassCastException e) { + // The activity doesn't implement the interface, throw exception + throw new ClassCastException(this.toString() + + " must implement NoticeDialogListener"); + } + } + + /** + * Creates the Dialog to add the name and rate of a new service that + * the admin has added to the list of services. + * + * @param savedInstanceState Bundle to transfer information. + * @return Dialog that is sent to admin for information. + */ + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + // Get the layout inflater + LayoutInflater inflater = getActivity().getLayoutInflater(); + View view = inflater.inflate(R.layout.dialog_service_new, null); + + + // Inflate and set the layout for the dialog + // Pass null as the parent view because its going in the dialog layout + builder.setView(view) + // Add action buttons + .setPositiveButton(R.string.add, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + EditText nameInput = (EditText) ((AlertDialog) dialog).findViewById(R.id.NameInput); + EditText rateInput = (EditText) ((AlertDialog) dialog).findViewById(R.id.RateInput); + String name = nameInput.getText().toString(); + DBHelper dbHelper = new DBHelper(getContext()); + if (rateInput.getText().toString().length()>0 && !rateInput.getText().toString().equals(".") && name.length()>0 && name.matches("^[a-zA-Z0-9_ ]*$") && dbHelper.findService(name)==null){ + Double rate = Double.parseDouble(rateInput.getText().toString()); + Bundle args = new Bundle(); + args.putString("name", name); + args.putDouble("rate", rate); + NewServiceDialogFragment.this.setArguments(args); + mListener.onDialogNew(NewServiceDialogFragment.this); + } + else if(!(rateInput.getText().toString().length()>0) || !(name.length()>0)|| !name.matches("[a-zA-Z]*") || !rateInput.getText().toString().equals(".")){ + Toast.makeText(getContext(), "Service must have an alphanumeric name and a rate", Toast.LENGTH_LONG).show(); + } + else{ + Toast.makeText(getContext(), "Service already exists", Toast.LENGTH_LONG).show(); + } + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + NewServiceDialogFragment.this.getDialog().cancel(); + } + }); + return builder.create(); + } + +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/PasswordEncryption.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/PasswordEncryption.java new file mode 100644 index 0000000..e0f91d5 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/PasswordEncryption.java @@ -0,0 +1,80 @@ +package com.uottawa.olympus.olympusservices; + +import android.os.Message; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.lang.Math; + +public class PasswordEncryption { + private static final MessageDigest MESSAGE_DIGEST; + private static final char[] POSSIBLE_CHARS; + private static final SecureRandom random; + + static{ + MessageDigest messageDigest; + try{ + messageDigest = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e){ + messageDigest = null; + } + MESSAGE_DIGEST = messageDigest; + + POSSIBLE_CHARS = new char[94]; + for (int i = 33; i<127; i++){ + POSSIBLE_CHARS[i-33] = (char)i; + } + + random = new SecureRandom(); + } + + public static String encrypt(String password, String salt){ + password = salt + password; + + byte[] passwordBytes = password.getBytes(); + byte[] hashedPassword; + + MESSAGE_DIGEST.reset(); + MESSAGE_DIGEST.update(passwordBytes); + hashedPassword = MESSAGE_DIGEST.digest(); + + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < hashedPassword.length; i++) { + if ((hashedPassword[i] & 0xff) < 0x10) { + sb.append("0"); + } + + sb.append(Long.toString(hashedPassword[i] & 0xff, 16)); + } + return sb.toString(); + } + + public static String generateSalt(){ + long stringID = Math.abs(random.nextLong()); + String salt = ""; + + while(stringID > 0){ + //the least significant digit is added to nonce string first + int index = (int)(stringID%94); + salt += POSSIBLE_CHARS[index]; + stringID /= 94; + } + return salt; + } + + public static boolean slowEquals(String one, String two){ + byte[] first = one.getBytes(); + byte[] second = two.getBytes(); + + int length = first.length > second.length ? second.length : first.length; + boolean same = true; + for (int i = 0; i serviceProviders; + + /** + * Constructor for a new service which uses the parameters + * to fill in the fields of the service and creates an arrayList + * for all the providers that provide that service. + * + * @param name String of the name of service. + * @param rate double of the price of service. + */ + Service(String name, double rate) { + this.name = name; + this.rate = rate; + serviceProviders = new ArrayList(); + } + + /** + * Gets the Name field of the service. + * + * @return String of the name. + */ + public String getName() { + return name; + } + + /** + * Gets the Rate field of the service. + * + * @return double of the rate. + */ + public double getRate() { + return rate; + } + + /** + * Changes the name field of the object to parameter given. + * + * @param name String object of new name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Changes the rate field of the object to parameter given. + * + * @param rate double of new rate. + */ + public void setRate(double rate) { + this.rate = rate; + } + + /** + * Adds a new service provider that offers this service into the list + * of service providers that offer this service. + * + * @param user Service Provider object which is added to the service's list. + * @return boolean of if the Service provider has been added. + */ + public boolean addServiceProvider(ServiceProvider user){ + for (ServiceProvider listUser : serviceProviders){ + if (user.getUsername().equals(listUser.getUsername())){ + return false; + } + } + serviceProviders.add(user); + return true; + } + + public List getServiceProviders(){ + return serviceProviders; + } +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProvider.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProvider.java new file mode 100644 index 0000000..774f7e1 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProvider.java @@ -0,0 +1,207 @@ +package com.uottawa.olympus.olympusservices; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * The service provider is the child userType class. The service provider + * class provides services which the homeowner can buy in the app. + * + */ + +public class ServiceProvider extends UserType { + + //Field for list of services that service provider offers. + private List services; + //Field for array of availabilities + /* + DO NOT CHANGE THIS ARRAY. The 2D array size is hard coded such that the first array has a size + of 7 and the array inside has an array size of 4. The array is setup such that the index represent a day of the + week. Monday is 0, Tuesday is 1, Wednesday is 2, Thursday is 3, Friday is 4, Saturday is 5, + Sunday is 6. so, [Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]. Inside each of + the arrays there is a another array containing int values such that index 0,1,2,3 is startHour, + startMin, endHour, endMin respectively. + */ + private int[][] availabilities; + + private String address; + private String phonenumber; + private String companyname; + private boolean licensed; + private String description; + private int rating; + + + + + /** + * Constructor for the service object which takes the parameters to + * fill out the service providers field. + * + * @param username String of the username. + * @param password String of the password. + * @param firstname String of the firstname. + * @param lastname String of the lastname. + */ + ServiceProvider(String username, String password, String firstname, String lastname, String address, + String phonenumber, String companyname, boolean licensed){ + this(username, password, firstname, lastname, address, phonenumber, companyname, licensed, ""); + } + + /** + * + * @param username + * @param password + * @param firstname + * @param lastname + * @param address + * @param phonenumber + * @param companyname + * @param licensed + * @param description + */ + ServiceProvider(String username, String password, String firstname, String lastname, String address, + String phonenumber, String companyname, boolean licensed, String description){ + super(username, password, firstname, lastname); + services = new ArrayList<>(); + availabilities = new int[7][4]; + this.address = address; + this.phonenumber = phonenumber; + this.companyname = companyname; + this.licensed = licensed; + this.description = description; + this.rating = 0; + } + + /** + * + * @param username + * @param hash + * @param salt + * @param firstname + * @param lastname + * @param address + * @param phonenumber + * @param companyname + * @param licensed + * @param description + */ + ServiceProvider(String username, String hash, String salt, String firstname, String lastname, String address, + String phonenumber, String companyname, boolean licensed, String description){ + super(username, hash, salt, firstname, lastname); + services = new ArrayList<>(); + availabilities = new int[7][4]; + this.address = address; + this.phonenumber = phonenumber; + this.companyname = companyname; + this.licensed = licensed; + this.description = description; + this.rating = 0; + } + + + /** + * gets the role of the UserType. + * + * @return String "Service Provider" + */ + public String getRole(){ return "ServiceProvider"; } + + /** + * adds service to the to service list if the service is in the + * database list of services. + * + * @param service Service object which is added to the services field. + * @return boolean whether service is added. + */ + public boolean addService(Service service){ + for (Service listService : services){ + if (service.getName().equals(listService.getName())){ + return false; + } + } + services.add(service); + return true; + } + + /** + * Gets the services list field of service provider. + * + * @return arrayList of Services + */ + + + + public void setAvailabilities(int day, int startHour, int startMin, int endHour, int endMin){ + availabilities[day][0] = startHour; + availabilities[day][1] = startMin; + availabilities[day][2] = endHour; + availabilities[day][3] = endMin; + } + + public int[][] getAvailabilities(){ + return availabilities; + } + + public void setAvailabilities(int[][] availabilities) { + this.availabilities = availabilities; + } + + public void setServices(List services) { + this.services = services; + } + + public List getServices(){ + return services; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhonenumber() { + return phonenumber; + } + + public void setPhonenumber(String phonenumber) { + this.phonenumber = phonenumber; + } + + public String getCompanyname() { + return companyname; + } + + public void setCompanyname(String companyname) { + this.companyname = companyname; + } + + public boolean isLicensed() { + return licensed; + } + + public void setLicensed(boolean licensed) { + this.licensed = licensed; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public int getRating() { + return rating; + } + + public void setRating(int rating) { + this.rating = rating; + } + +} \ No newline at end of file diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderAvailabilities.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderAvailabilities.java new file mode 100644 index 0000000..2898772 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderAvailabilities.java @@ -0,0 +1,241 @@ +package com.uottawa.olympus.olympusservices; + +import android.app.TimePickerDialog; +import android.content.Intent; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.TimePicker; +import android.widget.Toast; + +import java.util.Calendar; + +/** + * + * This class is the java class for the Service Provider's Availabilities menu. This class generates the menu from + * the saved Availabilities that the user has set previously or on default set no Availabilities. + * The menu gives the option to change availabilities for each day of the week or remove his availability on that + * day. User will receive a toast if they set impossible availabilities or they will receive a toast saying + * that their availabilities have been saved. + * + */ + +public class ServiceProviderAvailabilities extends AppCompatActivity { + private String username; + + /** + * This class generates the availabilities from the serviceProvider class fields + * on creation of this menu so the user can edit and change it on the menu. + * + * @param savedInstanceState + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_service_provider_availabilities); + Bundle bundle = getIntent().getExtras(); + username = bundle.getString("username"); + DBHelper dbHelper = new DBHelper(this); + ServiceProvider user = (ServiceProvider) dbHelper.findUserByUsername(username); + int[][] days = user.getAvailabilities(); + String startTime; + String endTime; + int i = 0; + for(int[] times: days){ + startTime = formatTime(times[0],times[1]); + endTime = formatTime(times[2],times[3]); + if(times[0]==0&×[1]==0&×[2]==0&×[3]==0){ + startTime = "START"; + endTime = "END"; + } + if(i==0){ + ((Button)findViewById(R.id.MondayStart)).setText(startTime); + ((Button)findViewById(R.id.MondayEnd)).setText(endTime); + }else if(i==1){ + ((Button)findViewById(R.id.TuesdayStart)).setText(startTime); + ((Button)findViewById(R.id.TuesdayEnd)).setText(endTime); + }else if(i==2){ + ((Button)findViewById(R.id.WednesdayStart)).setText(startTime); + ((Button)findViewById(R.id.WednesdayEnd)).setText(endTime); + }else if(i==3){ + ((Button)findViewById(R.id.ThursdayStart)).setText(startTime); + ((Button)findViewById(R.id.ThursdayEnd)).setText(endTime); + }else if(i==4){ + ((Button)findViewById(R.id.FridayStart)).setText(startTime); + ((Button)findViewById(R.id.FridayEnd)).setText(endTime); + }else if(i==5){ + ((Button)findViewById(R.id.SaturdayStart)).setText(startTime); + ((Button)findViewById(R.id.SaturdayEnd)).setText(endTime); + }else if(i==6){ + ((Button)findViewById(R.id.SundayStart)).setText(startTime); + ((Button)findViewById(R.id.SundayEnd)).setText(endTime); + } + i++; + } + } + + + public void onClick(View v) { + // Get Current Time + final Calendar c = Calendar.getInstance(); + int hour = c.get(Calendar.HOUR_OF_DAY); + int minute = c.get(Calendar.MINUTE); + final Button button = (Button)v; + + // Launch Time Picker Dialog + TimePickerDialog timePickerDialog = new TimePickerDialog(this, + new TimePickerDialog.OnTimeSetListener() { + + @Override + public void onTimeSet(TimePicker view, int hourOfDay, + int minute) { + String time = ""; + + button.setText(formatTime(hourOfDay,minute)); + //set availibility for service provider and check start time is less than finish + } + + }, hour, minute, false); + timePickerDialog.show(); + } + + public void onRemove(View view){ + //set time to Start/End, set availibility for start and end to null + Button start; + Button end; + if(view.getId()==R.id.DeleteMon){ + start = findViewById(R.id.MondayStart); + end = findViewById(R.id.MondayEnd); + start.setText("START"); + end.setText("END"); + }else if(view.getId()==R.id.DeleteTuesday){ + start = findViewById(R.id.TuesdayStart); + end = findViewById(R.id.TuesdayEnd); + start.setText("START"); + end.setText("END"); + }else if(view.getId()==R.id.DeleteWednesday){ + start = findViewById(R.id.WednesdayStart); + end = findViewById(R.id.WednesdayEnd); + start.setText("START"); + end.setText("END"); + }else if(view.getId()==R.id.DeleteThursday){ + start = findViewById(R.id.ThursdayStart); + end = findViewById(R.id.ThursdayEnd); + start.setText("START"); + end.setText("END"); + }else if(view.getId()==R.id.DeleteFriday){ + start = findViewById(R.id.FridayStart); + end = findViewById(R.id.FridayEnd); + start.setText("START"); + end.setText("END"); + }else if(view.getId()==R.id.DeleteSaturday){ + start = findViewById(R.id.SaturdayStart); + end = findViewById(R.id.SaturdayEnd); + start.setText("START"); + end.setText("END"); + }else{ + start = findViewById(R.id.SundayStart); + end = findViewById(R.id.SundayEnd); + start.setText("START"); + end.setText("END"); + } + } + + /** + * Parses the views of the UI to generate 2D int array and updates the database and user with + * the new 2D on click of the setTime button. + * + * @param view + */ + public void onSetTimes(View view){ + int[] mondayTime = parseTime( ((Button)findViewById(R.id.MondayStart)).getText().toString(),((Button)findViewById(R.id.MondayEnd)).getText().toString() ); + int[] tuesdayTime = parseTime( ((Button)findViewById(R.id.TuesdayStart)).getText().toString(),((Button)findViewById(R.id.TuesdayEnd)).getText().toString() ); + int[] wednesdayTime = parseTime( ((Button)findViewById(R.id.WednesdayStart)).getText().toString(),((Button)findViewById(R.id.WednesdayEnd)).getText().toString() ); + int[] thursdayTime = parseTime( ((Button)findViewById(R.id.ThursdayStart)).getText().toString(),((Button)findViewById(R.id.ThursdayEnd)).getText().toString() ); + int[] fridayTime = parseTime( ((Button)findViewById(R.id.FridayStart)).getText().toString(), ((Button)findViewById(R.id.FridayEnd)).getText().toString() ); + int[] saturdayTime = parseTime( ((Button)findViewById(R.id.SaturdayStart)).getText().toString(),((Button)findViewById(R.id.SaturdayEnd)).getText().toString() ); + int[] sundayTime = parseTime( ((Button)findViewById(R.id.SundayStart)).getText().toString(),((Button)findViewById(R.id.SundayEnd)).getText().toString() ); + int[][] availabilities = {mondayTime,tuesdayTime,wednesdayTime,thursdayTime,fridayTime,saturdayTime,sundayTime}; + boolean validation = true; + for(int[] times: availabilities){ + if(!validateTime(times)){ + validation = false; + } + } + if(validation){ + DBHelper dbHelper = new DBHelper(this); + ServiceProvider user = (ServiceProvider) dbHelper.findUserByUsername(username); + user.setAvailabilities(availabilities); + dbHelper.updateAvailability(user); + Toast.makeText(this, "New Availabilities have been set.", Toast.LENGTH_LONG).show(); + } else{ + Toast.makeText(this, "All end times must be later then start times.", Toast.LENGTH_LONG).show(); + } + + + } + + /** + * Override so that previous screen refreshes when pressing the + * back button on this activity of the app. + * + */ + @Override + public void onBackPressed(){ + Intent intent = new Intent(getApplicationContext(),ServiceProviderWelcome.class); + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + + private String formatTime(int hours, int minutes){ + String time = ""; + if(hours<10){ + time = time+"0"+hours+":"; + }else{ + time = time+hours+":"; + } + if (minutes<10){ + time = time+"0"+minutes; + } + else { + time = time+minutes; + } + return time; + } + + private int[] parseTime(String startTime, String endTime){ + int[] times = new int[4]; + if(startTime.equals("START")){ + times[0]=0; + times[1]=0; + }else{ + times[0] = Integer.parseInt(startTime.substring(0,2)); + times[1] = Integer.parseInt(startTime.substring(3)); + } + if(endTime.equals("END")){ + times[2]=0; + times[3]=0; + }else{ + times[2] = Integer.parseInt(endTime.substring(0,2)); + times[3] = Integer.parseInt(endTime.substring(3)); + } + return times; + } + + private boolean validateTime(int[] time){ + if(time[0]==0&&time[1]==0&&time[2]==0&&time[3]==0){ + return true; + } + if(time[2]>time[0]){ + return true; + }else{ + if(time[2]==time[0]&&time[3]>time[1]){ + return true; + }else{ + return false; + } + } + } +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderEditProfile.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderEditProfile.java new file mode 100644 index 0000000..11eae79 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderEditProfile.java @@ -0,0 +1,108 @@ +package com.uottawa.olympus.olympusservices; + +import android.content.Intent; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; +import android.widget.CheckBox; +import android.widget.TextView; +import android.widget.Toast; + +public class ServiceProviderEditProfile extends AppCompatActivity { + String username; + DBHelper dbHelper; + + /** + * Prepoplates the fields with user information when the activity is created + * @param savedInstanceState + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_service_provider_edit_profile); + Bundle bundle = getIntent().getExtras(); + username = bundle.getString("username"); + dbHelper = new DBHelper(this); + ServiceProvider user; + user = (ServiceProvider)dbHelper.findUserByUsername(username); + TextView firstname = findViewById(R.id.FirstNameInput); + TextView lastname = findViewById(R.id.LastNameInput); + TextView password = findViewById(R.id.PasswordInput); + TextView companyname = findViewById(R.id.CompanyNameInput); + TextView address = findViewById(R.id.AddressInput); + TextView phonenumber = findViewById(R.id.PhoneNumberInput); + TextView description = findViewById(R.id.DescriptionInput); + CheckBox licensed = findViewById(R.id.LicensedInput); + + + firstname.setText(user.getFirstname()); + lastname.setText(user.getLastname()); + password.setText(""); + companyname.setText(user.getCompanyname()); + address.setText(user.getAddress()); + phonenumber.setText(user.getPhonenumber()); + description.setText(user.getDescription()); + licensed.setChecked(user.isLicensed()); + + } + + /** + * Override so that previous screen refreshes when pressing the + * back button on this activity of the app. + * + */ + @Override + public void onBackPressed(){ + Intent intent = new Intent(getApplicationContext(),ServiceProviderWelcome.class); + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + + /** + * Saves updated user information to the database + * @param view + */ + public void Save(View view){ + TextView firstname = findViewById(R.id.FirstNameInput); + TextView lastname = findViewById(R.id.LastNameInput); + TextView password = findViewById(R.id.PasswordInput); + TextView companyname = findViewById(R.id.CompanyNameInput); + TextView address = findViewById(R.id.AddressInput); + TextView phonenumber = findViewById(R.id.PhoneNumberInput); + TextView description = findViewById(R.id.DescriptionInput); + CheckBox licensed = findViewById(R.id.LicensedInput); + + //Checks for the fields + if((password.getText().toString().length()>=5 || password.getText().toString().equals("")) + && firstname.getText().toString().length()>0 + && lastname.getText().toString().length()>0 && companyname.getText().toString().length()>0 + && address.getText().toString().length()>0 && phonenumber.getText().toString().length()>0 + && password.getText().toString().matches("[a-zA-Z0-9]*") + && firstname.getText().toString().matches("[a-zA-Z]*") + && lastname.getText().toString().matches("[a-zA-Z]*") + && companyname.getText().toString().matches("^[a-zA-Z0-9_ ]*$") + && address.getText().toString().matches("^[a-zA-Z0-9_ ]*$") + && description.getText().toString().matches("^[a-zA-Z0-9_ ]*$") + && phonenumber.getText().toString().matches("^(\\+\\d{1,2}\\s)?\\(?\\d{3}\\)?[\\s.-]?\\d{3}[\\s.-]?\\d{4}$") + && address.getText().toString().replaceAll("\\s+","").length()>0) { + + + if(dbHelper.updateUserInfo(username, password.getText().toString(), firstname.getText().toString(), lastname.getText().toString(), + address.getText().toString(), phonenumber.getText().toString(), companyname.getText().toString(), licensed.isChecked(), description.getText().toString())){ + //add comment method here + Toast.makeText(this, "Profile has been updated", Toast.LENGTH_LONG).show(); + } + else{ + Toast.makeText(this, "Could not update profile ", Toast.LENGTH_LONG).show(); + + } + + } + else{ + Toast.makeText(this, "Fields cannot be empty (other than description) and must be formatted correctly", Toast.LENGTH_LONG).show(); + } + } + + +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderServicesList.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderServicesList.java new file mode 100644 index 0000000..36105c0 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderServicesList.java @@ -0,0 +1,232 @@ +package com.uottawa.olympus.olympusservices; + +import android.content.Context; +import android.content.Intent; +import android.support.annotation.NonNull; +import android.support.design.widget.Snackbar; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; +import android.widget.Toast; + +import com.jaredrummler.materialspinner.MaterialSpinner; + +import java.util.Iterator; +import java.util.List; + +/** + * Creates the view and dialog listener for List of services + * which the admin can view and manipulate. + * + */ +public class ServiceProviderServicesList extends AppCompatActivity implements DeleteServiceDialogFragment.NoticeDialogListener{ + + //field for RecyclerView + private RecyclerView mRecyclerView; + //field for adapter of Recycler view + private RecyclerView.Adapter mAdapter; + //field for layout manager of Recyler view. + private RecyclerView.LayoutManager mLayoutManager; + + private String username; + + /** + * On creation loads up the xml, and generates the services list, + * and fills out the recylerView fields. + * + * @param savedInstanceState Bundle to transfer information. + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_service_provider_services_list); + + Bundle bundle = getIntent().getExtras(); + username = bundle.getString("username"); + DBHelper dbHelper = new DBHelper(this); + + //grid + List serviceslist2 = dbHelper.getAllServicesProvidedByUser(username); + Service[] services2 = new Service[(serviceslist2.size())]; + Iterator iter2 = serviceslist2.iterator(); + for (int i=0; i serviceslist = dbHelper.getAllServices(); + String[] services = new String[(serviceslist.size())]; + Iterator iter = serviceslist.iterator(); + for (int i=0; i { + + private Service[] services; + private Context context; + + // Provide a reference to the views for each data item + // Complex data items may need more than one view per item, and + // you provide access to all the views for a data item in a view holder + + // Provide a suitable constructor (depends on the kind of dataset) + public MyAdapter(Service[] services, Context context) { + this.services = services; + } + + // Create new views (invoked by the layout manager) + @NonNull + @Override + public ServicesHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.service_list_item, parent, false); + ServicesHolder vh = new ServicesHolder(v); + return vh; + } + + // Replace the contents of a view (invoked by the layout manager) + @Override + public void onBindViewHolder(ServicesHolder holder, int position) { + Service service = services[position]; + holder.name.setText(service.getName()); + holder.rate.setText(String.format("$%,.2f", service.getRate())); + + + + } + + // Return the size of your dataset (invoked by the layout manager) + @Override + public int getItemCount() { + return services.length; + } + + //nested class for the items in the recycler view + class ServicesHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ + + TextView name; + TextView rate; + + public ServicesHolder(View row){ + super(row); + name = row.findViewById(R.id.Name); + rate = row.findViewById(R.id.Rate); + row.setOnClickListener(this); + } + + /** + * Onclick function for the items in the recycler view + * @param view + */ + @Override + public void onClick(View view) { + TextView nameview = (TextView)view.findViewById(R.id.Name); + String name = nameview.getText().toString(); + deleteService(view, name); + + } + + + } + + + } + +} \ No newline at end of file diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderWelcome.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderWelcome.java new file mode 100644 index 0000000..2b34266 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/ServiceProviderWelcome.java @@ -0,0 +1,89 @@ +package com.uottawa.olympus.olympusservices; + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; +import android.content.Intent; + +/** + * Welcome class creates the welcome screen for the HomeOwners and ServiceProviders + * as a temporary screen until full functionality of those two a classes are + * implemented. + * + */ +public class ServiceProviderWelcome extends AppCompatActivity { + String username; + + /** + * On creation of this object the app will display the xml file for + * the welcome page which gets the role and username of the UserType + * object and welcomes the user with a message. + * + * @param savedInstanceState Bundle to transfer data + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_service_provider_welcome); + Bundle bundle = getIntent().getExtras(); + username = bundle.getString("username"); + DBHelper dbHelper = new DBHelper(this); + UserType user; + user = dbHelper.findUserByUsername(username); + TextView welcome = findViewById(R.id.Welcome); + welcome.setText("Welcome "+user.getFirstname()+ " you are logged in as a Service Provider"); + + + } + + /** + * Override so that nothing occurs when pressing the + * back button on this activity of the app. + * + */ + @Override + public void onBackPressed(){ + } + + /** + * Logs out the user and returns them back to + * main activity. End all current user activity + * for security purposes. + * + * @param view View object of current activity. + */ + public void LogOut(View view){ + Intent intent = new Intent(getApplicationContext(), Main.class); + startActivity(intent); + finish(); + } + + public void EditProfile(View view){ + Intent intent = new Intent(getApplicationContext(),ServiceProviderEditProfile.class); + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + + public void EditServices(View view){ + Intent intent = new Intent(getApplicationContext(),ServiceProviderServicesList.class); + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + public void EditAvailabilities(View view){ + Intent intent = new Intent(getApplicationContext(),ServiceProviderAvailabilities.class); + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + public void SeeBookings(View view){ + Intent intent = new Intent(getApplicationContext(),Bookings.class); + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + + +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/SignUp.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/SignUp.java index 770795e..299c5ee 100644 --- a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/SignUp.java +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/SignUp.java @@ -4,22 +4,123 @@ import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import com.jaredrummler.materialspinner.MaterialSpinner; import android.support.design.widget.Snackbar; +import android.content.Intent; +import android.widget.EditText; +import android.view.View; +import android.widget.Toast; + +/** + * This class is used to create new userType where the user + * fills in his information and his data is sent to to the database + * to create a new userType object. + * + */ public class SignUp extends AppCompatActivity { + + /** + * On creation of this class the xml page is loaded up onto the app and + * the EditTexts are set up to accept the information of the user. + * + * @param savedInstanceState Bundle for transferring information + */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_up); MaterialSpinner spinner = findViewById(R.id.RoleInput); - spinner.setItems("Ice Cream Sandwich", "Jelly Bean", "KitKat", "Lollipop", "Marshmallow"); + spinner.setItems("Home Owner", "Service Provider"); spinner.setOnItemSelectedListener(new MaterialSpinner.OnItemSelectedListener() { @Override public void onItemSelected(MaterialSpinner view, int position, long id, String item) { Snackbar.make(view, "Clicked " + item, Snackbar.LENGTH_LONG).show(); } }); - } - public static void main(String[] args){ } + + /** + * On click creates a new user if the the user information + * fits the criteria specified by the documentation and is + * not a duplicate of another user. + * + * @param view View object that contains all the editText and buttons used. + */ + public void onClickSignUp(View view){ + UserType newUser; + String username = ((EditText) findViewById(R.id.UsernameInput)).getText().toString(); + String password = ((EditText) findViewById(R.id.PasswordInput)).getText().toString(); + String firstname = ((EditText) findViewById(R.id.FirstNameInput)).getText().toString(); + String lastname = ((EditText) findViewById(R.id.LastNameInput)).getText().toString(); + MaterialSpinner spinner = findViewById(R.id.RoleInput); + + if(username.length()>=5 && password.length()>=5 && firstname.length()>0 && lastname.length()>0 + && username.matches("[a-zA-Z0-9]*") && password.matches("[a-zA-Z0-9]*") + && firstname.matches("[a-zA-Z]*") && lastname.matches("[a-zA-Z]*")){ + DBHelper dbHelper = new DBHelper(this); + Intent intent = new Intent(getApplicationContext(),LogIn.class); + switch(spinner.getText().toString()){ + case "Home Owner": + newUser = new HomeOwner(username,password,firstname,lastname); + if(dbHelper.addUser(newUser)){ + startActivity(intent); + finish(); + }else{ + Toast.makeText(this,"Username is taken",Toast.LENGTH_LONG).show(); + } + break; + case "Service Provider": + if(dbHelper.findUserByUsername(username)==null) { + Intent intent2 = new Intent(getApplicationContext(), SignUpPart2.class); + intent2.putExtra("firstname", firstname); + intent2.putExtra("lastname", lastname); + intent2.putExtra("username", username); + intent2.putExtra("password", password); + startActivity(intent2); + finish(); + }else{ + Toast.makeText(this,"Username is taken",Toast.LENGTH_LONG).show(); + } + break; + + default: + newUser = new HomeOwner(username,password,firstname,lastname); //if nothing is enter then defaults to user role. + + if(dbHelper.addUser(newUser)){ + startActivity(intent); + finish(); + }else{ + Toast.makeText(this,"Username is taken",Toast.LENGTH_LONG).show(); + } + break; + + } + + } + else if(firstname.length()==0 || lastname.length()==0 || username.length()==0 || password.length()==0){ + Toast.makeText(this, "Fields cannot be empty", Toast.LENGTH_LONG).show(); + } + else if (username.length()<5 || password.length()<5 ){ + Toast.makeText(this, "Password and username must be longer than 4 characters", Toast.LENGTH_LONG).show(); + } + else{ + Toast.makeText(this, "Fields may only contain alphanumeric values", Toast.LENGTH_LONG).show(); + } + } + + /** + * app closes the the activity when back is pressed and + * no user information written down is saved in the EditText for + * security purposes. + */ + + @Override + public void onBackPressed(){ + Intent intent = new Intent(getApplicationContext(), Main.class); + startActivity(intent); + finish(); + } + + + } diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/SignUpPart2.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/SignUpPart2.java new file mode 100644 index 0000000..7eb5913 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/SignUpPart2.java @@ -0,0 +1,58 @@ +package com.uottawa.olympus.olympusservices; + +import android.content.Intent; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.Toast; + +public class SignUpPart2 extends AppCompatActivity { + private String username; + private String password; + private String firstname; + private String lastname; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_sign_up_part2); + Bundle bundle = getIntent().getExtras(); + username = bundle.getString("username"); + password = bundle.getString("password"); + firstname = bundle.getString("firstname"); + lastname = bundle.getString("lastname"); + } + + public void SignUp(View view){ + DBHelper dbHelper = new DBHelper(this); + Intent intent = new Intent(getApplicationContext(),LogIn.class); + String companyname = ((EditText) findViewById(R.id.CompanyNameInput)).getText().toString(); + String phonenumber = ((EditText) findViewById(R.id.PhoneNumberInput)).getText().toString(); + String address = ((EditText) findViewById(R.id.AddressInput)).getText().toString(); + boolean licensed = ((CheckBox) findViewById(R.id.LicensedInput)).isChecked(); + String description = ((EditText) findViewById(R.id.DescriptionInput)).getText().toString(); + + if(companyname.length()>0 && address.length()>0 && phonenumber.length()>0 + && companyname.matches("^[a-zA-Z0-9_ ]*$") && address.matches("^[a-zA-Z0-9_ ]*$") + && phonenumber.matches("^(\\+\\d{1,2}\\s)?\\(?\\d{3}\\)?[\\s.-]?\\d{3}[\\s.-]?\\d{4}$") + && description.matches("^[a-zA-Z0-9_ ]*$") + && companyname.replaceAll("\\s+","").length()>0 + && address.replaceAll("\\s+","").length()>0) { + + ServiceProvider serviceProvider = new ServiceProvider(username, password, firstname, lastname, + address, phonenumber, companyname, licensed, description); + if(dbHelper.addUser(serviceProvider)){ + startActivity(intent); + finish(); + }else{ + Toast.makeText(this,"Could not create account",Toast.LENGTH_LONG).show(); + } + } + else{ + Toast.makeText(this, "Fields cannot be empty and must be formatted correctly", Toast.LENGTH_LONG).show(); + } + + } +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/UserType.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/UserType.java new file mode 100644 index 0000000..cb6e502 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/UserType.java @@ -0,0 +1,173 @@ +package com.uottawa.olympus.olympusservices; + + +import java.io.Serializable; + +/** + * UserType is the abstract object that is the parent class + * of all users in this program with all common methods and + * fields set in this one class. + */ + +public abstract class UserType { + + //field for the username attached to the userType. + String username; + //field for the password hash attached to the userType. + String hash; + //field for the firstname attached to the userType. + String firstname; + //field for the lastname attached to the userType. + String lastname; + //field for the salt attached to the userType. + String salt; + + + /** + * Constructor filling out all the field values with given parameters + * entered by a new user for the app. + * + * @param username String object containing the username. + * @param password String object containing the password. + * @param firstname String object containing the firstname. + * @param lastname String object containing the lastname. + */ + UserType(String username, String password, String firstname, String lastname){ + this.username = username; + this.firstname = firstname; + this.lastname = lastname; + + this.salt = PasswordEncryption.generateSalt(); + this.hash = PasswordEncryption.encrypt(password, salt); + } + + /** + * Constructor filling out all the field values with given parameters + * entered by a new user for the app. + * + * @param username String object containing the username. + * @param hash String object containing the password hash. + * @param firstname String object containing the firstname. + * @param lastname String object containing the lastname. + * @param salt String object containing the salt. + */ + UserType(String username, String hash, String salt, String firstname, String lastname){ + this.username = username; + this.firstname = firstname; + this.lastname = lastname; + + this.salt = salt; + this.hash = hash; + } + + /** + * Abstract method to get the role of each userType child in the app. + * + * @return String object specifying the role of userType. + */ + public abstract String getRole(); + + /** + * Gets the username field of userType. + * + * @return String of the username. + */ + public String getUsername() { + return username; + } + + /** + * Gets the hash field of userType. + * + * @return String of the hash. + */ + public String getHash() { + return hash; + } + + /** + * Gets the firstname field of userType. + * + * @return String of firstname + */ + public String getFirstname() { + return firstname; + } + + /** + * Gets the lastname field of userType. + * + * @return String of lastname + */ + public String getLastname() { + return lastname; + } + + /** + * Gets the salt field of userType. + * + * @return String of salt + */ + public String getSalt() { + return salt; + } + + /** + * Sets the username field with given parameters. + * + * @param username String for new username. + */ + public void setUsername(String username) { + //remember to call updateUser(String username, String password, String firstname, String lastname) + //in activity whenever a setter is called. DBHelper requires a Context (Activity) to be initialized + //so cannot be initialized in this class + this.username = username; + + } + + /** + * Sets the password field with given parameters. + * + * @param password String of new password. + */ + public void setPassword(String password) { + //remember to call updateUser(String username, String password, String firstname, String lastname) + //in activity whenever a setter is called. DBHelper requires a Context (Activity) to be initialized + //so cannot be initialized in this class + this.salt = PasswordEncryption.generateSalt(); + this.hash = PasswordEncryption.encrypt(password, salt); + } + + /** + * Sets the firstname field with given parameters. + * + * @param firstname String of new firstname. + */ + public void setFirstname(String firstname) { + //remember to call updateUser(String username, String password, String firstname, String lastname) + //in activity whenever a setter is called. DBHelper requires a Context (Activity) to be initialized + //so cannot be initialized in this class + this.firstname = firstname; + } + + public void setLastname(String lastname) { + //remember to call updateUser(String username, String password, String firstname, String lastname) + //in activity whenever a setter is called. DBHelper requires a Context (Activity) to be initialized + //so cannot be initialized in this class + this.lastname = lastname; + } + + /** + * Compares this userType and another userType to see if there fields are equal. + * + * @param other Usertype object that is compared to this userType. + */ + public boolean equals(UserType other){ + if(this.username.equals(other.username)&&this.hash.equals(other.hash)&& + this.firstname.equals(other.firstname)&&this.lastname.equals(other.lastname) + &&this.salt.equals(other.salt)){ + return true; + } + return false; + } +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/UsersList.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/UsersList.java new file mode 100644 index 0000000..f407880 --- /dev/null +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/UsersList.java @@ -0,0 +1,129 @@ +package com.uottawa.olympus.olympusservices; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.GridView; +import android.widget.TextView; + +import java.util.Iterator; +import java.util.List; + +/** + * screen for user list that the admin can access + * and manage all users in the program. Userlist is generated through + * the database using DBHelper class. + * + */ + +public class UsersList extends AppCompatActivity { + + /** + * on Creation of this class the app loads up the xml page for + * activity_user_list and generates a gridview using the database + * for all the users in the app. + * + * @param savedInstanceState bundle to transfer data + */ + + //field for RecyclerView + private RecyclerView mRecyclerView; + //field for adapter of Recycler view + private RecyclerView.Adapter mAdapter; + //field for layout manager of Recyler view. + private RecyclerView.LayoutManager mLayoutManager; + + private DBHelper dbHelper; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_users_list); + + dbHelper = new DBHelper(this); + List users = dbHelper.getAllUsers(); + String[] usernames = new String[(users.size())]; + Iterator iter = users.iterator(); + for (int i=0; i { + + private String[] users; + private Context context; + + // Provide a reference to the views for each data item + // Complex data items may need more than one view per item, and + // you provide access to all the views for a data item in a view holder + + // Provide a suitable constructor (depends on the kind of dataset) + public MyAdapter(String[] users, Context context) { + this.users = users; + } + + // Create new views (invoked by the layout manager) + @NonNull + @Override + public UsersHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.user_list_item, parent, false); + return new UsersHolder(v); + } + + // Replace the contents of a view (invoked by the layout manager) + @Override + public void onBindViewHolder(UsersHolder holder, int position) { + UserType user = dbHelper.findUserByUsername(users[position]); + holder.name.setText(user.getUsername()); + holder.rate.setText(user.getRole()); + + + + } + + // Return the size of your dataset (invoked by the layout manager) + @Override + public int getItemCount() { + return users.length; + } + + class UsersHolder extends RecyclerView.ViewHolder{ + + TextView name; + TextView rate; + + public UsersHolder(View row){ + super(row); + name = row.findViewById(R.id.Name); + rate = row.findViewById(R.id.Role); + } + + } + + + } + + +} diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Welcome.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Welcome.java index 8cf6848..8ee61e6 100644 --- a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Welcome.java +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/Welcome.java @@ -2,12 +2,82 @@ package com.uottawa.olympus.olympusservices; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; +import android.view.View; +import android.widget.TextView; +import android.content.Intent; +/** + * Welcome class creates the welcome screen for the HomeOwners and ServiceProviders + * as a temporary screen until full functionality of those two a classes are + * implemented. + * + */ public class Welcome extends AppCompatActivity { + String username; + /** + * On creation of this object the app will display the xml file for + * the welcome page which gets the role and username of the UserType + * object and welcomes the user with a message. + * + * @param savedInstanceState Bundle to transfer data + */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_welcome); + Bundle bundle = getIntent().getExtras(); + username = bundle.getString("username"); + DBHelper dbHelper = new DBHelper(this); + UserType user; + user = dbHelper.findUserByUsername(username); + TextView welcome = findViewById(R.id.Welcome); + welcome.setText("Welcome "+user.getFirstname()+ " you are logged in as a Home Owner"); + + + } + + /** + * Override so that nothing occurs when pressing the + * back button on this activity of the app. + * + */ + @Override + public void onBackPressed(){ + } + + /** + * Logs out the user and returns them back to + * main activity. End all current user activity + * for security purposes. + * + * @param view View object of current activity. + */ + public void LogOut(View view){ + Intent intent = new Intent(getApplicationContext(), Main.class); + startActivity(intent); + finish(); + } + + public void SeeBookings(View view){ + Intent intent = new Intent(getApplicationContext(),Bookings.class); + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + + public void FindServiceProvider(View view){ + Intent intent = new Intent(getApplicationContext(),FindServiceProvider.class); + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + public void EditProfile(View view){ + Intent intent = new Intent(getApplicationContext(),HomeOwnerEditProfile.class); + intent.putExtra("username", username); + startActivity(intent); + finish(); + } + } diff --git a/OlympusServices/app/src/main/res/drawable/customborder2.xml b/OlympusServices/app/src/main/res/drawable/customborder2.xml new file mode 100644 index 0000000..6e6dfe4 --- /dev/null +++ b/OlympusServices/app/src/main/res/drawable/customborder2.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/OlympusServices/app/src/main/res/drawable/logo.JPG b/OlympusServices/app/src/main/res/drawable/logo.JPG new file mode 100644 index 0000000..65459c1 Binary files /dev/null and b/OlympusServices/app/src/main/res/drawable/logo.JPG differ diff --git a/OlympusServices/app/src/main/res/layout/activity_admin_services_list.xml b/OlympusServices/app/src/main/res/layout/activity_admin_services_list.xml new file mode 100644 index 0000000..2c19a56 --- /dev/null +++ b/OlympusServices/app/src/main/res/layout/activity_admin_services_list.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + +