Appointment activities
This commit is contained in:
@@ -0,0 +1,86 @@
|
|||||||
|
package com.example.petstoremobile.adapters;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import com.example.petstoremobile.R;
|
||||||
|
import com.example.petstoremobile.models.Appointment;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AppointmentAdapter extends RecyclerView.Adapter<AppointmentAdapter.AppointmentViewHolder> {
|
||||||
|
|
||||||
|
private List<Appointment> appointmentList;
|
||||||
|
private OnAppointmentClickListener appointmentClickListener;
|
||||||
|
|
||||||
|
// Interface for appointment click on recycler view
|
||||||
|
public interface OnAppointmentClickListener {
|
||||||
|
void onAppointmentClick(int position);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public AppointmentAdapter(List<Appointment> appointmentList, OnAppointmentClickListener appointmentClickListener) {
|
||||||
|
this.appointmentList = appointmentList;
|
||||||
|
this.appointmentClickListener = appointmentClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the controls of each row in recycler view
|
||||||
|
public static class AppointmentViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView tvCustomerName, tvPetName, tvServiceType, tvDateTime, tvAppointmentStatus;
|
||||||
|
|
||||||
|
public AppointmentViewHolder(@NonNull View v) {
|
||||||
|
super(v);
|
||||||
|
tvCustomerName = v.findViewById(R.id.tvCustomerName);
|
||||||
|
tvPetName = v.findViewById(R.id.tvApptPetName);
|
||||||
|
tvServiceType = v.findViewById(R.id.tvServiceType);
|
||||||
|
tvDateTime = v.findViewById(R.id.tvDateTime);
|
||||||
|
tvAppointmentStatus = v.findViewById(R.id.tvAppointmentStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new row view
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public AppointmentViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_appointment, parent, false);
|
||||||
|
return new AppointmentViewHolder(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate the row with appointment data
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull AppointmentViewHolder holder, int position) {
|
||||||
|
Appointment appointment = appointmentList.get(position);
|
||||||
|
|
||||||
|
holder.tvCustomerName.setText(appointment.getCustomerName());
|
||||||
|
holder.tvPetName.setText("Pet: " + appointment.getPetName());
|
||||||
|
holder.tvServiceType.setText(appointment.getServiceType());
|
||||||
|
holder.tvDateTime.setText(appointment.getAppointmentDate() + " at " + appointment.getAppointmentTime());
|
||||||
|
holder.tvAppointmentStatus.setText(appointment.getStatus());
|
||||||
|
|
||||||
|
// Set the status color depending on appointment status
|
||||||
|
switch (appointment.getStatus()) {
|
||||||
|
case "Confirmed":
|
||||||
|
holder.tvAppointmentStatus.setBackgroundColor(Color.parseColor("#4CAF50"));
|
||||||
|
break;
|
||||||
|
case "Pending":
|
||||||
|
holder.tvAppointmentStatus.setBackgroundColor(Color.parseColor("#FF9800"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
holder.tvAppointmentStatus.setBackgroundColor(Color.parseColor("#F44336"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When a row is clicked, open the detail view
|
||||||
|
holder.itemView.setOnClickListener(v -> appointmentClickListener.onAppointmentClick(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return appointmentList.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
package com.example.petstoremobile.fragments.listfragments;
|
||||||
|
|
||||||
|
// Added search/filter bar to filter appointments by customer name or service type.
|
||||||
|
// Added pull-to-refresh using SwipeRefreshLayout.
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import com.example.petstoremobile.R;
|
||||||
|
import com.example.petstoremobile.adapters.AppointmentAdapter;
|
||||||
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
|
import com.example.petstoremobile.fragments.listfragments.detailfragments.AppointmentDetailFragment;
|
||||||
|
import com.example.petstoremobile.models.Appointment;
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AppointmentFragment extends Fragment implements AppointmentAdapter.OnAppointmentClickListener {
|
||||||
|
|
||||||
|
private List<Appointment> appointmentList = new ArrayList<>(); // full data list
|
||||||
|
private List<Appointment> filteredList = new ArrayList<>(); // filtered display list
|
||||||
|
private AppointmentAdapter adapter;
|
||||||
|
private SwipeRefreshLayout swipeRefreshLayout;
|
||||||
|
private EditText etSearch;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.fragment_appointment, container, false);
|
||||||
|
|
||||||
|
loadAppointmentData(); // TODO: Replace with actual API call when backend is ready
|
||||||
|
setupRecyclerView(view);
|
||||||
|
setupSearch(view);
|
||||||
|
setupSwipeRefresh(view);
|
||||||
|
|
||||||
|
FloatingActionButton fabAddAppointment = view.findViewById(R.id.fabAddAppointment);
|
||||||
|
fabAddAppointment.setOnClickListener(v -> openAppointmentDetails(-1));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets up the search bar to filter appointments by customer name or service type
|
||||||
|
private void setupSearch(View view) {
|
||||||
|
etSearch = view.findViewById(R.id.etSearchAppointment);
|
||||||
|
etSearch.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
|
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
filterAppointments(s.toString());
|
||||||
|
}
|
||||||
|
@Override public void afterTextChanged(Editable s) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filters the appointment list based on the search query
|
||||||
|
private void filterAppointments(String query) {
|
||||||
|
filteredList.clear();
|
||||||
|
if (query.isEmpty()) {
|
||||||
|
filteredList.addAll(appointmentList);
|
||||||
|
} else {
|
||||||
|
String lower = query.toLowerCase();
|
||||||
|
for (Appointment a : appointmentList) {
|
||||||
|
if (a.getCustomerName().toLowerCase().contains(lower)
|
||||||
|
|| a.getServiceType().toLowerCase().contains(lower)
|
||||||
|
|| a.getPetName().toLowerCase().contains(lower)) {
|
||||||
|
filteredList.add(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets up pull-to-refresh: reloads data when user swipes down
|
||||||
|
private void setupSwipeRefresh(View view) {
|
||||||
|
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshAppointment);
|
||||||
|
swipeRefreshLayout.setOnRefreshListener(() -> {
|
||||||
|
loadAppointmentData(); // TODO: Replace with actual API call when backend is ready
|
||||||
|
filterAppointments(etSearch.getText().toString());
|
||||||
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openAppointmentDetails(int position) {
|
||||||
|
AppointmentDetailFragment detailFragment = new AppointmentDetailFragment();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putInt("position", position);
|
||||||
|
|
||||||
|
if (position != -1) {
|
||||||
|
Appointment appointment = filteredList.get(position);
|
||||||
|
// Find the real position in the full list for save/delete callbacks
|
||||||
|
int realPosition = appointmentList.indexOf(appointment);
|
||||||
|
args.putInt("position", realPosition);
|
||||||
|
args.putInt("appointmentId", appointment.getAppointmentId());
|
||||||
|
args.putString("customerName", appointment.getCustomerName());
|
||||||
|
args.putString("petName", appointment.getPetName());
|
||||||
|
args.putString("serviceType", appointment.getServiceType());
|
||||||
|
args.putString("appointmentDate", appointment.getAppointmentDate());
|
||||||
|
args.putString("appointmentTime", appointment.getAppointmentTime());
|
||||||
|
args.putString("status", appointment.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
detailFragment.setArguments(args);
|
||||||
|
detailFragment.setAppointmentFragment(this);
|
||||||
|
|
||||||
|
ListFragment listFragment = (ListFragment) getParentFragment();
|
||||||
|
if (listFragment != null) listFragment.loadFragment(detailFragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onAppointmentSaved(int position, Appointment appointment) {
|
||||||
|
if (position == -1) {
|
||||||
|
appointmentList.add(appointment);
|
||||||
|
} else {
|
||||||
|
appointmentList.set(position, appointment);
|
||||||
|
}
|
||||||
|
filterAppointments(etSearch.getText().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onAppointmentDeleted(int position) {
|
||||||
|
appointmentList.remove(position);
|
||||||
|
filterAppointments(etSearch.getText().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAppointmentClick(int position) {
|
||||||
|
openAppointmentDetails(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to load hardcoded sample data
|
||||||
|
// Replace with API call
|
||||||
|
private void loadAppointmentData() {
|
||||||
|
appointmentList.clear();
|
||||||
|
appointmentList.add(new Appointment(1, "John Smith", "Buddy", "Grooming", "2026-03-10", "10:00 AM", "Confirmed"));
|
||||||
|
appointmentList.add(new Appointment(2, "Jane Doe", "Luna", "Vet Checkup", "2026-03-11", "02:00 PM", "Pending"));
|
||||||
|
appointmentList.add(new Appointment(3, "Bob Lee", "Max", "Training", "2026-03-12", "11:00 AM", "Confirmed"));
|
||||||
|
appointmentList.add(new Appointment(4, "Alice Brown", "Milo", "Grooming", "2026-03-13", "03:00 PM", "Cancelled"));
|
||||||
|
filteredList.clear();
|
||||||
|
filteredList.addAll(appointmentList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupRecyclerView(View view) {
|
||||||
|
RecyclerView recyclerView = view.findViewById(R.id.recyclerViewAppointments);
|
||||||
|
adapter = new AppointmentAdapter(filteredList, this); // adapter uses filteredList
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
package com.example.petstoremobile.fragments.listfragments.detailfragments;
|
||||||
|
|
||||||
|
|
||||||
|
// Uses InputValidator for detailed field validation and ActivityLogger to log all changes.
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import com.example.petstoremobile.R;
|
||||||
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
|
import com.example.petstoremobile.fragments.listfragments.AppointmentFragment;
|
||||||
|
import com.example.petstoremobile.models.Appointment;
|
||||||
|
import com.example.petstoremobile.utils.ActivityLogger;
|
||||||
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
|
|
||||||
|
public class AppointmentDetailFragment extends Fragment {
|
||||||
|
|
||||||
|
private TextView tvMode, tvAppointmentId;
|
||||||
|
private EditText etCustomerName, etPetName, etServiceType, etAppointmentDate, etAppointmentTime;
|
||||||
|
private Spinner spinnerStatus;
|
||||||
|
private Button btnSaveAppointment, btnDeleteAppointment, btnBack;
|
||||||
|
private int appointmentId;
|
||||||
|
private int position;
|
||||||
|
private boolean isEditing = false;
|
||||||
|
private AppointmentFragment appointmentFragment;
|
||||||
|
|
||||||
|
// Set the appointment fragment as parent so we refer back when save or delete is done
|
||||||
|
public void setAppointmentFragment(AppointmentFragment fragment) {
|
||||||
|
this.appointmentFragment = fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.fragment_appointment_detail, container, false);
|
||||||
|
|
||||||
|
initViews(view);
|
||||||
|
setupSpinner();
|
||||||
|
handleArguments();
|
||||||
|
|
||||||
|
btnBack.setOnClickListener(v -> {
|
||||||
|
ListFragment listFragment = (ListFragment) getParentFragment();
|
||||||
|
if (listFragment != null) {
|
||||||
|
listFragment.getChildFragmentManager().popBackStack();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
btnSaveAppointment.setOnClickListener(v -> saveAppointment());
|
||||||
|
btnDeleteAppointment.setOnClickListener(v -> deleteAppointment());
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validates all fields using InputValidator, then saves the appointment
|
||||||
|
private void saveAppointment() {
|
||||||
|
// Validate all inputs using InputValidator utility
|
||||||
|
if (!InputValidator.isNotEmpty(etCustomerName, "Customer Name")) return;
|
||||||
|
if (!InputValidator.isNotEmpty(etPetName, "Pet Name")) return;
|
||||||
|
if (!InputValidator.isNotEmpty(etServiceType, "Service Type")) return;
|
||||||
|
if (!InputValidator.isValidDate(etAppointmentDate)) return;
|
||||||
|
if (!InputValidator.isValidTime(etAppointmentTime)) return;
|
||||||
|
|
||||||
|
String customerName = etCustomerName.getText().toString().trim();
|
||||||
|
String petName = etPetName.getText().toString().trim();
|
||||||
|
String serviceType = etServiceType.getText().toString().trim();
|
||||||
|
String date = etAppointmentDate.getText().toString().trim();
|
||||||
|
String time = etAppointmentTime.getText().toString().trim();
|
||||||
|
String status = spinnerStatus.getSelectedItem().toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isEditing) {
|
||||||
|
// TODO: Replace with actual API PUT call when backend is ready
|
||||||
|
Appointment updated = new Appointment(appointmentId, customerName, petName, serviceType, date, time, status);
|
||||||
|
if (appointmentFragment != null) appointmentFragment.onAppointmentSaved(position, updated);
|
||||||
|
ActivityLogger.logChange(requireContext(), "Appointment", "UPDATED", appointmentId);
|
||||||
|
Toast.makeText(getContext(), "Appointment updated.", Toast.LENGTH_SHORT).show();
|
||||||
|
} else {
|
||||||
|
// TODO: Replace with actual API POST call when backend is ready
|
||||||
|
Appointment newAppt = new Appointment(0, customerName, petName, serviceType, date, time, status);
|
||||||
|
if (appointmentFragment != null) appointmentFragment.onAppointmentSaved(-1, newAppt);
|
||||||
|
ActivityLogger.log(requireContext(), "Added new Appointment for customer: " + customerName);
|
||||||
|
Toast.makeText(getContext(), "Appointment added.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
// Go back to list
|
||||||
|
ListFragment listFragment = (ListFragment) getParentFragment();
|
||||||
|
if (listFragment != null) listFragment.getChildFragmentManager().popBackStack();
|
||||||
|
} catch (Exception e) {
|
||||||
|
ActivityLogger.logException(requireContext(), "AppointmentDetailFragment.saveAppointment", e);
|
||||||
|
Toast.makeText(getContext(), "Error saving appointment.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deletes the appointment and logs the action
|
||||||
|
private void deleteAppointment() {
|
||||||
|
try {
|
||||||
|
// TODO: Replace with actual API DELETE call when backend is ready
|
||||||
|
if (appointmentFragment != null) appointmentFragment.onAppointmentDeleted(position);
|
||||||
|
ActivityLogger.logChange(requireContext(), "Appointment", "DELETED", appointmentId);
|
||||||
|
Toast.makeText(getContext(), "Appointment deleted.", Toast.LENGTH_SHORT).show();
|
||||||
|
ListFragment listFragment = (ListFragment) getParentFragment();
|
||||||
|
if (listFragment != null) listFragment.getChildFragmentManager().popBackStack();
|
||||||
|
} catch (Exception e) {
|
||||||
|
ActivityLogger.logException(requireContext(), "AppointmentDetailFragment.deleteAppointment", e);
|
||||||
|
Toast.makeText(getContext(), "Error deleting appointment.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determines if the fragment is in add or edit mode and populates fields accordingly
|
||||||
|
private void handleArguments() {
|
||||||
|
if (getArguments() != null && getArguments().containsKey("appointmentId")) {
|
||||||
|
isEditing = true;
|
||||||
|
appointmentId = getArguments().getInt("appointmentId");
|
||||||
|
position = getArguments().getInt("position");
|
||||||
|
tvMode.setText("Edit Appointment");
|
||||||
|
tvAppointmentId.setText("ID: " + appointmentId);
|
||||||
|
etCustomerName.setText(getArguments().getString("customerName"));
|
||||||
|
etPetName.setText(getArguments().getString("petName"));
|
||||||
|
etServiceType.setText(getArguments().getString("serviceType"));
|
||||||
|
etAppointmentDate.setText(getArguments().getString("appointmentDate"));
|
||||||
|
etAppointmentTime.setText(getArguments().getString("appointmentTime"));
|
||||||
|
String status = getArguments().getString("status");
|
||||||
|
if ("Confirmed".equals(status)) spinnerStatus.setSelection(0);
|
||||||
|
else if ("Pending".equals(status)) spinnerStatus.setSelection(1);
|
||||||
|
else spinnerStatus.setSelection(2);
|
||||||
|
btnDeleteAppointment.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
isEditing = false;
|
||||||
|
tvMode.setText("Add Appointment");
|
||||||
|
tvAppointmentId.setVisibility(View.GONE);
|
||||||
|
btnDeleteAppointment.setVisibility(View.GONE);
|
||||||
|
btnSaveAppointment.setText("Add");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initViews(View view) {
|
||||||
|
tvMode = view.findViewById(R.id.tvApptMode);
|
||||||
|
tvAppointmentId = view.findViewById(R.id.tvAppointmentId);
|
||||||
|
etCustomerName = view.findViewById(R.id.etCustomerName);
|
||||||
|
etPetName = view.findViewById(R.id.etApptPetName);
|
||||||
|
etServiceType = view.findViewById(R.id.etServiceType);
|
||||||
|
etAppointmentDate = view.findViewById(R.id.etAppointmentDate);
|
||||||
|
etAppointmentTime = view.findViewById(R.id.etAppointmentTime);
|
||||||
|
spinnerStatus = view.findViewById(R.id.spinnerAppointmentStatus);
|
||||||
|
btnSaveAppointment = view.findViewById(R.id.btnSaveAppointment);
|
||||||
|
btnDeleteAppointment = view.findViewById(R.id.btnDeleteAppointment);
|
||||||
|
btnBack = view.findViewById(R.id.btnApptBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupSpinner() {
|
||||||
|
ArrayAdapter<String> adapter = new ArrayAdapter<>(requireContext(),
|
||||||
|
android.R.layout.simple_spinner_item,
|
||||||
|
new String[]{"Confirmed", "Pending", "Cancelled"});
|
||||||
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
spinnerStatus.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package com.example.petstoremobile.models;
|
||||||
|
|
||||||
|
|
||||||
|
public class Appointment {
|
||||||
|
private int appointmentId;
|
||||||
|
private String customerName;
|
||||||
|
private String petName;
|
||||||
|
private String serviceType;
|
||||||
|
private String appointmentDate;
|
||||||
|
private String appointmentTime;
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
public Appointment(int appointmentId, String customerName, String petName, String serviceType, String appointmentDate, String appointmentTime, String status) {
|
||||||
|
this.appointmentId = appointmentId;
|
||||||
|
this.customerName = customerName;
|
||||||
|
this.petName = petName;
|
||||||
|
this.serviceType = serviceType;
|
||||||
|
this.appointmentDate = appointmentDate;
|
||||||
|
this.appointmentTime = appointmentTime;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters and setters
|
||||||
|
public int getAppointmentId() {
|
||||||
|
return appointmentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCustomerName() {
|
||||||
|
return customerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerName(String customerName) {
|
||||||
|
this.customerName = customerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPetName() {
|
||||||
|
return petName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPetName(String petName) {
|
||||||
|
this.petName = petName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServiceType() {
|
||||||
|
return serviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServiceType(String serviceType) {
|
||||||
|
this.serviceType = serviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppointmentDate() {
|
||||||
|
return appointmentDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppointmentDate(String appointmentDate) {
|
||||||
|
this.appointmentDate = appointmentDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppointmentTime() {
|
||||||
|
return appointmentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppointmentTime(String appointmentTime) {
|
||||||
|
this.appointmentTime = appointmentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
52
app/src/main/res/layout/fragment_appointment.xml
Normal file
52
app/src/main/res/layout/fragment_appointment.xml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!-- Updated: added search bar and SwipeRefreshLayout for pull-to-refresh -->
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#F5F5F5">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etSearchAppointment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:hint="Search by customer, pet or service..."
|
||||||
|
android:inputType="text"
|
||||||
|
android:drawableStart="@android:drawable/ic_menu_search"
|
||||||
|
android:drawablePadding="8dp"
|
||||||
|
android:background="@android:color/white"
|
||||||
|
android:padding="12dp"/>
|
||||||
|
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/swipeRefreshAppointment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recyclerViewAppointments"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="8dp"/>
|
||||||
|
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/fabAddAppointment"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:contentDescription="Add Appointment"
|
||||||
|
app:srcCompat="@android:drawable/ic_input_add"/>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
101
app/src/main/res/layout/fragment_appointment_detail.xml
Normal file
101
app/src/main/res/layout/fragment_appointment_detail.xml
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#F5F5F5">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/main"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="20dp"
|
||||||
|
android:paddingRight="20dp"
|
||||||
|
android:paddingTop="20dp"
|
||||||
|
android:paddingBottom="20dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvApptMode"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:fontFamily="sans-serif-black"
|
||||||
|
android:text="Add Appointment"
|
||||||
|
android:textColor="@color/text_dark"
|
||||||
|
android:textSize="25sp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnDeleteAppointment"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Delete" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvAppointmentId"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
android:text="ID: 0" />
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||||
|
android:text="Customer Name" android:textColor="@color/text_dark" android:textSize="12sp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
<EditText android:id="@+id/etCustomerName" android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" android:hint="Enter customer name"
|
||||||
|
android:inputType="text" android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||||
|
android:text="Pet Name" android:textColor="@color/text_dark" android:textSize="12sp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
<EditText android:id="@+id/etApptPetName" android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" android:hint="Enter pet name"
|
||||||
|
android:inputType="text" android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||||
|
android:text="Service Type" android:textColor="@color/text_dark" android:textSize="12sp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
<EditText android:id="@+id/etServiceType" android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" android:hint="e.g. Grooming, Vet Checkup"
|
||||||
|
android:inputType="text" android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||||
|
android:text="Appointment Date" android:textColor="@color/text_dark" android:textSize="12sp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
<EditText android:id="@+id/etAppointmentDate" android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" android:hint="YYYY-MM-DD"
|
||||||
|
android:inputType="text" android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||||
|
android:text="Appointment Time" android:textColor="@color/text_dark" android:textSize="12sp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
<EditText android:id="@+id/etAppointmentTime" android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" android:hint="e.g. 10:00 AM"
|
||||||
|
android:inputType="text" android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||||
|
android:text="Status" android:textColor="@color/text_dark" android:textSize="12sp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
<Spinner android:id="@+id/spinnerAppointmentStatus" android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" android:layout_marginBottom="32dp"/>
|
||||||
|
|
||||||
|
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
<Button android:id="@+id/btnApptBack" android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content" android:layout_weight="1"
|
||||||
|
android:layout_marginRight="10dp" android:text="Back"/>
|
||||||
|
<Button android:id="@+id/btnSaveAppointment" android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content" android:layout_weight="1"
|
||||||
|
android:layout_marginLeft="10dp" android:text="Save"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
|
||||||
74
app/src/main/res/layout/item_appointment.xml
Normal file
74
app/src/main/res/layout/item_appointment.xml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:background="@android:color/white">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvCustomerName"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Customer Name"
|
||||||
|
android:textColor="#000000"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvAppointmentStatus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="#4CAF50"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingTop="4dp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:paddingBottom="4dp"
|
||||||
|
android:text="Status"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvApptPetName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:text="Pet: name"
|
||||||
|
android:textColor="#666666"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvServiceType"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:text="Service type"
|
||||||
|
android:textColor="#666666"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvDateTime"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:text="Date and time"
|
||||||
|
android:textColor="#2196F3"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="#EEEEEE"
|
||||||
|
android:layout_marginTop="12dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
Reference in New Issue
Block a user