Commit ecd23c3b authored by Syazmin's avatar Syazmin

Appointment Details and Listing Done

parent 7d9fc201
This diff is collapsed.
{
"java.configuration.updateBuildConfiguration": "interactive"
}
\ No newline at end of file
......@@ -40,6 +40,7 @@ dependencies {
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.activity:activity:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
// Test implementation
testImplementation 'junit:junit:4.13.2'
......
......@@ -27,6 +27,12 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- NEW: Appointment List Activity -->
<activity
android:name=".AppointmentListActivity"
android:exported="false"
android:label="Appointments" />
</application>
</manifest>
\ No newline at end of file
package com.example.qmsmakeappointment;
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 java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class AppointmentAdapterNew extends RecyclerView.Adapter<AppointmentAdapterNew.ViewHolder> {
private List<AppointmentEntity> appointments = new ArrayList<>();
private final OnAppointmentClickListener listener;
private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("EEE, d MMM yyyy", Locale.getDefault());
public interface OnAppointmentClickListener {
void onAppointmentClick(AppointmentEntity appointment);
}
public AppointmentAdapterNew(OnAppointmentClickListener listener) {
this.listener = listener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_appointment_new, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
AppointmentEntity appointment = appointments.get(position);
// Show date header only if it's a different date from previous item
if (position == 0 || !isSameDate(appointments.get(position - 1), appointment)) {
holder.dateHeader.setVisibility(View.VISIBLE);
LocalDate date = LocalDate.ofEpochDay(appointment.getSelectedDate());
holder.dateHeader.setText(date.format(dateFormatter));
} else {
holder.dateHeader.setVisibility(View.GONE);
}
// Set time
holder.time.setText(appointment.getSelectedTime());
// Set unit number
holder.unit.setText(appointment.getUnitNo());
// Set owner name (representative name from form)
String ownerName = appointment.getRepresentativeName();
if (ownerName != null && !ownerName.isEmpty()) {
holder.location.setText(ownerName);
} else {
holder.location.setText("No owner name");
}
// Set type badge
String type = appointment.getAppointmentType();
holder.typeBadge.setText(type);
// Set badge background based on type
if (type.equals("Handover")) {
holder.typeBadge.setBackgroundResource(R.drawable.badge_handover);
} else if (type.equals("Rectification")) {
holder.typeBadge.setBackgroundResource(R.drawable.badge_rectification);
} else if (type.equals("Joint Inspection")) {
holder.typeBadge.setBackgroundResource(R.drawable.badge_joint_inspection);
} else if (type.equals("Viewing")) {
holder.typeBadge.setBackgroundResource(R.drawable.badge_confirmed);
} else {
holder.typeBadge.setBackgroundResource(R.drawable.badge_handover);
}
// Click listener
holder.itemView.setOnClickListener(v -> listener.onAppointmentClick(appointment));
}
@Override
public int getItemCount() {
return appointments.size();
}
public void setAppointments(List<AppointmentEntity> appointments) {
this.appointments = appointments;
notifyDataSetChanged();
}
private boolean isSameDate(AppointmentEntity a1, AppointmentEntity a2) {
return a1.getSelectedDate() == a2.getSelectedDate();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView dateHeader;
TextView time;
TextView unit;
TextView typeBadge;
TextView location;
ViewHolder(View itemView) {
super(itemView);
dateHeader = itemView.findViewById(R.id.date_header);
time = itemView.findViewById(R.id.appointment_time);
unit = itemView.findViewById(R.id.appointment_unit);
typeBadge = itemView.findViewById(R.id.appointment_type_badge);
location = itemView.findViewById(R.id.appointment_location);
}
}
}
package com.example.qmsmakeappointment;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
......@@ -15,6 +16,29 @@ public interface AppointmentDao {
@Update
void updateAppointment(AppointmentEntity appointment);
@Delete
void deleteAppointment(AppointmentEntity appointment);
@Query("SELECT * FROM appointments ORDER BY selectedDate DESC")
List<AppointmentEntity> getAllAppointments();
// NEW QUERIES FOR APPOINTMENT LISTING
@Query("SELECT * FROM appointments WHERE appointmentType = :type ORDER BY selectedDate DESC")
List<AppointmentEntity> getAppointmentsByType(String type);
@Query("SELECT * FROM appointments WHERE selectedDate >= :currentDate ORDER BY selectedDate ASC")
List<AppointmentEntity> getUpcomingAppointments(long currentDate);
@Query("SELECT * FROM appointments WHERE selectedDate < :currentDate ORDER BY selectedDate DESC")
List<AppointmentEntity> getHistoryAppointments(long currentDate);
@Query("SELECT * FROM appointments WHERE id = :appointmentId")
AppointmentEntity getAppointmentById(int appointmentId);
@Query("UPDATE appointments SET status = :status WHERE id = :appointmentId")
void updateAppointmentStatus(int appointmentId, String status);
@Query("SELECT * FROM appointments WHERE status = :status ORDER BY selectedDate DESC")
List<AppointmentEntity> getAppointmentsByStatus(String status);
}
......@@ -6,7 +6,7 @@ import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
@Database(entities = {AppointmentEntity.class}, version = 1, exportSchema = false)
@Database(entities = {AppointmentEntity.class}, version = 2, exportSchema = false)
public abstract class AppointmentDatabase extends RoomDatabase {
public abstract AppointmentDao appointmentDao();
......@@ -19,6 +19,7 @@ public abstract class AppointmentDatabase extends RoomDatabase {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppointmentDatabase.class, "appointment_database")
.fallbackToDestructiveMigration() // Allow destructive migration for now
.build();
}
}
......
......@@ -18,6 +18,12 @@ public class AppointmentEntity {
private String contactNumber;
private String attachmentPath;
// for Appointment Listing
private String appointmentType;
private String status;
private String location;
private long createdTimestamp;
public AppointmentEntity(String unitNo, long selectedDate, String selectedTime, String representativeName, String contactEmail, String contactNumber, String attachmentPath) {
this.unitNo = unitNo;
this.selectedDate = selectedDate;
......@@ -26,6 +32,12 @@ public class AppointmentEntity {
this.contactEmail = contactEmail;
this.contactNumber = contactNumber;
this.attachmentPath = attachmentPath;
// Set default values for new fields
this.appointmentType = "Handover"; // Default type
this.status = "Confirmed"; // Default status
this.location = "A2-1-2, Block A, Ashlar Residence, 63105, Selangor"; // Default location
this.createdTimestamp = System.currentTimeMillis(); // Current time
}
// Getters and setters (Required for room)
......@@ -46,4 +58,14 @@ public class AppointmentEntity {
public String getAttachmentPath() { return attachmentPath; }
public void setAttachmentPath(String attachmentPath) { this.attachmentPath = attachmentPath; }
// NEW GETTERS AND SETTERS
public String getAppointmentType() { return appointmentType; }
public void setAppointmentType(String appointmentType) { this.appointmentType = appointmentType; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getLocation() { return location; }
public void setLocation(String location) { this.location = location; }
public long getCreatedTimestamp() { return createdTimestamp; }
public void setCreatedTimestamp(long createdTimestamp) { this.createdTimestamp = createdTimestamp; }
}
package com.example.qmsmakeappointment;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.RadioGroup;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.bottomsheet.BottomSheetDialog;
public class AppointmentListActivity extends AppCompatActivity {
private ImageButton backButton;
private ImageButton filterButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_appointment_list);
backButton = findViewById(R.id.back_button);
filterButton = findViewById(R.id.filter_button);
// Load the appointment list fragment
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container_list, new AppointmentListFragmentNew())
.commit();
}
// Back button - handle fragment back stack or close activity
backButton.setOnClickListener(v -> {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
// If there are fragments in the back stack, pop them
getSupportFragmentManager().popBackStack();
} else {
// Otherwise, close the activity
finish();
}
});
// Filter button - Can be used for additional sorting options if needed
filterButton.setOnClickListener(v -> showFilterDialog());
}
private void showFilterDialog() {
BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(this);
View dialogView = getLayoutInflater().inflate(R.layout.bottom_sheet_filter, null);
bottomSheetDialog.setContentView(dialogView);
// Get radio groups
RadioGroup radioGroupSort = dialogView.findViewById(R.id.radio_group_sort);
RadioGroup radioGroupType = dialogView.findViewById(R.id.radio_group_type);
RadioGroup radioGroupStatus = dialogView.findViewById(R.id.radio_group_status);
// Get buttons
Button btnReset = dialogView.findViewById(R.id.btn_reset_filter);
Button btnApply = dialogView.findViewById(R.id.btn_apply_filter);
// Reset button - reset all to default
btnReset.setOnClickListener(v -> {
radioGroupSort.check(R.id.radio_newest_first);
radioGroupType.check(R.id.radio_all_types);
radioGroupStatus.check(R.id.radio_all_status);
});
// Apply button - apply filter to the list fragment
btnApply.setOnClickListener(v -> {
int sortId = radioGroupSort.getCheckedRadioButtonId();
int typeId = radioGroupType.getCheckedRadioButtonId();
int statusId = radioGroupStatus.getCheckedRadioButtonId();
// Get the fragment
AppointmentListFragmentNew fragment = (AppointmentListFragmentNew) getSupportFragmentManager()
.findFragmentById(R.id.fragment_container_list);
if (fragment != null) {
// Determine sort order
String sortOrder = "newest";
if (sortId == R.id.radio_oldest_first) sortOrder = "oldest";
else if (sortId == R.id.radio_date_ascending) sortOrder = "date_asc";
else if (sortId == R.id.radio_date_descending) sortOrder = "date_desc";
// Determine type filter
String typeFilter = null;
if (typeId == R.id.radio_handover_only) typeFilter = "Handover";
else if (typeId == R.id.radio_viewing_only) typeFilter = "Viewing";
// Determine status filter
String statusFilter = null;
if (statusId == R.id.radio_confirmed_only) statusFilter = "Confirmed";
else if (statusId == R.id.radio_cancelled_only) statusFilter = "Cancelled";
else if (statusId == R.id.radio_completed_only) statusFilter = "Completed";
// Apply filter
fragment.applyFilter(sortOrder, typeFilter, statusFilter);
}
bottomSheetDialog.dismiss();
});
bottomSheetDialog.show();
}
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
// If there are fragments in the back stack, pop them
getSupportFragmentManager().popBackStack();
} else {
// Otherwise, use default back behavior
try {
super.onBackPressed();
} catch (Exception e) {
finish();
}
}
}
}
......@@ -14,6 +14,7 @@ public class AppointmentViewModel extends ViewModel {
private final MutableLiveData<String> contactEmail = new MutableLiveData<>();
private final MutableLiveData<String> contactNumber = new MutableLiveData<>();
private final MutableLiveData<Boolean> isRepresentativeAttending = new MutableLiveData<>(false);
private final MutableLiveData<String> appointmentType = new MutableLiveData<>("Handover"); // Default to Handover
// Getters
public LiveData<String> getUnitNo() { return unitNo; }
......@@ -23,6 +24,7 @@ public class AppointmentViewModel extends ViewModel {
public LiveData<String> getContactEmail() { return contactEmail; }
public LiveData<String> getContactNumber() { return contactNumber; }
public LiveData<Boolean> isRepresentativeAttending() { return isRepresentativeAttending; }
public LiveData<String> getAppointmentType() { return appointmentType; }
// Setters
public void setSelectedDate(long date) { selectedDate.setValue(date); }
......@@ -31,6 +33,7 @@ public class AppointmentViewModel extends ViewModel {
public void setContactEmail(String email) { contactEmail.setValue(email); }
public void setContactNumber(String number) { contactNumber.setValue(number); }
public void setRepresentativeAttending(boolean isAttending) { isRepresentativeAttending.setValue(isAttending); }
public void setAppointmentType(String type) { appointmentType.setValue(type); }
public void clearRepresentativeData() {
representativeName.setValue(null);
......@@ -43,6 +46,7 @@ public class AppointmentViewModel extends ViewModel {
selectedDate.setValue(null);
selectedTime.setValue(null);
isRepresentativeAttending.setValue(false);
appointmentType.setValue("Handover"); // Reset to default
clearRepresentativeData();
}
}
package com.example.qmsmakeappointment;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ImageButton;
import android.widget.Toast;
......@@ -98,19 +99,27 @@ public class MainActivity extends AppCompatActivity {
null // Placeholder for attachment path
);
// Set the appointment type from ViewModel
if (viewModel.getAppointmentType().getValue() != null) {
newAppointment.setAppointmentType(viewModel.getAppointmentType().getValue());
}
// Run database insert on a background thread
executorService.execute(() -> {
db.appointmentDao().insertAppointment(newAppointment);
// Post success back to the main thread
runOnUiThread(() -> {
// Show Access Alert
Toast.makeText(MainActivity.this, "Success: You have successfully made a appointment.", Toast.LENGTH_LONG).show();
// Clear back stack and restart to Terms & Conditions
// Clear back stack and reset ViewModel
getSupportFragmentManager().popBackStack(null, androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE);
viewModel.resetAppointment();
loadFragment(new TermsConditionsFragment(), false);
// Navigate to Appointment List Activity
Intent intent = new Intent(MainActivity.this, AppointmentListActivity.class);
startActivity(intent);
// Optionally finish this activity
finish();
});
});
}
......
package com.example.qmsmakeappointment;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.google.android.material.card.MaterialCardView;
public class Step0TypeFragment extends Fragment {
private AppointmentViewModel viewModel;
private MaterialCardView cardHandover, cardRectification, cardJointInspection, cardViewing;
private Button nextButton;
private String selectedType = null;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_step_0_type, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewModel = new ViewModelProvider(requireActivity()).get(AppointmentViewModel.class);
// Initialize views
cardHandover = view.findViewById(R.id.card_handover);
cardRectification = view.findViewById(R.id.card_rectification);
cardJointInspection = view.findViewById(R.id.card_joint_inspection);
cardViewing = view.findViewById(R.id.card_viewing);
nextButton = view.findViewById(R.id.next_button);
// Check if type was already selected (if user comes back)
if (viewModel.getAppointmentType().getValue() != null) {
selectedType = viewModel.getAppointmentType().getValue();
updateCardSelection();
enableNextButton();
}
// Set click listeners for cards
cardHandover.setOnClickListener(v -> selectType("Handover", cardHandover));
cardRectification.setOnClickListener(v -> selectType("Rectification", cardRectification));
cardJointInspection.setOnClickListener(v -> selectType("Joint Inspection", cardJointInspection));
cardViewing.setOnClickListener(v -> selectType("Viewing", cardViewing));
// Next button click listener
nextButton.setOnClickListener(v -> {
if (selectedType != null) {
viewModel.setAppointmentType(selectedType);
((MainActivity) requireActivity()).loadFragment(new Step1DateFragment(), true);
}
});
}
private void selectType(String type, MaterialCardView selectedCard) {
selectedType = type;
// Reset all cards
resetAllCards();
// Highlight selected card
int tealColor = ContextCompat.getColor(requireContext(), R.color.colorPrimary);
selectedCard.setStrokeColor(tealColor);
// Enable next button
enableNextButton();
}
private void resetAllCards() {
int transparentColor = ContextCompat.getColor(requireContext(), android.R.color.transparent);
cardHandover.setStrokeColor(transparentColor);
cardRectification.setStrokeColor(transparentColor);
cardJointInspection.setStrokeColor(transparentColor);
cardViewing.setStrokeColor(transparentColor);
}
private void updateCardSelection() {
resetAllCards();
int tealColor = ContextCompat.getColor(requireContext(), R.color.colorPrimary);
if ("Handover".equals(selectedType)) {
cardHandover.setStrokeColor(tealColor);
} else if ("Rectification".equals(selectedType)) {
cardRectification.setStrokeColor(tealColor);
} else if ("Joint Inspection".equals(selectedType)) {
cardJointInspection.setStrokeColor(tealColor);
} else if ("Viewing".equals(selectedType)) {
cardViewing.setStrokeColor(tealColor);
}
}
private void enableNextButton() {
nextButton.setEnabled(true);
int tealColor = ContextCompat.getColor(requireContext(), R.color.colorPrimary);
nextButton.setBackgroundTintList(ColorStateList.valueOf(tealColor));
}
}
......@@ -44,9 +44,9 @@ public class TermsConditionsFragment extends Fragment {
// Handle Agree and Next button click
agreeNextButton.setOnClickListener(v -> {
// Navigate to Step 1
// Navigate to appointment type selection step
if (getActivity() instanceof MainActivity) {
((MainActivity) getActivity()).loadFragment(new Step1DateFragment(), false);
((MainActivity) getActivity()).loadFragment(new Step0TypeFragment(), false);
}
});
}
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FF5252" />
<corners android:radius="12dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#9E9E9E" />
<corners android:radius="12dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4CAF50" />
<corners android:radius="12dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/colorPrimary" />
<corners android:radius="12dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#D32F2F"/>
<corners android:radius="12dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FF6B35"/>
<corners android:radius="12dp"/>
</shape>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="64"
android:viewportHeight="64">
<!-- Background -->
<path
android:fillColor="#F8F8F8"
android:pathData="M4,4 L60,4 L60,60 L4,60 Z"/>
<!-- Main building outline -->
<path
android:strokeColor="#333333"
android:strokeWidth="2"
android:fillColor="#00000000"
android:pathData="M12,12 L52,12 L52,52 L12,52 Z"/>
<!-- Vertical room divider (left) -->
<path
android:strokeColor="#666666"
android:strokeWidth="1.5"
android:pathData="M24,12 L24,52"/>
<!-- Vertical room divider (right) -->
<path
android:strokeColor="#666666"
android:strokeWidth="1.5"
android:pathData="M40,12 L40,52"/>
<!-- Horizontal divider (upper) -->
<path
android:strokeColor="#666666"
android:strokeWidth="1.5"
android:pathData="M12,26 L52,26"/>
<!-- Horizontal divider (lower) -->
<path
android:strokeColor="#666666"
android:strokeWidth="1.5"
android:pathData="M12,38 L52,38"/>
<!-- Door symbol -->
<path
android:strokeColor="#0E7392"
android:strokeWidth="2"
android:pathData="M28,52 L28,46 L34,46 L34,52"/>
<!-- Window symbols -->
<path
android:strokeColor="#999999"
android:strokeWidth="1.5"
android:pathData="M16,16 L20,16"/>
<path
android:strokeColor="#999999"
android:strokeWidth="1.5"
android:pathData="M44,16 L48,16"/>
<!-- Stairs indicator -->
<path
android:strokeColor="#999999"
android:strokeWidth="1"
android:pathData="M30,20 L34,20 M30,22 L34,22 M30,24 L34,24"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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">
<!-- Toolbar -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:background="@color/colorPrimary"
app:layout_constraintTop_toTopOf="parent">
<ImageButton
android:id="@+id/back_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="8dp"
android:background="@null"
android:contentDescription="Back"
android:src="@drawable/ic_chevron_left"
app:tint="@color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Appointment"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<ImageButton
android:id="@+id/filter_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="8dp"
android:background="@null"
android:contentDescription="Filter"
android:src="@android:drawable/ic_menu_sort_by_size"
app:tint="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- Fragment Container -->
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container_list"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/toolbar_layout"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="vertical"
android:padding="24dp"
android:background="@android:color/white">
<!-- Icon -->
<ImageView
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center_horizontal"
android:src="@android:drawable/ic_dialog_alert"
android:tint="#FF5252"
android:contentDescription="Cancel Icon" />
<!-- Title -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:text="Cancel Appointment?"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="#000000" />
<!-- Message -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:text="Are you sure you want to cancel this appointment? This action cannot be undone."
android:textSize="14sp"
android:textColor="#666666"
android:gravity="center"
android:lineSpacingExtra="4dp" />
<!-- Buttons Container -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="horizontal"
android:gravity="center">
<!-- No Button -->
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_no"
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:text="No, Keep It"
android:textSize="14sp"
android:textAllCaps="false"
style="@style/Widget.Material3.Button.OutlinedButton"
app:strokeColor="@color/colorPrimary"
app:strokeWidth="1dp"
android:textColor="@color/colorPrimary" />
<!-- Yes Button -->
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_yes"
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:text="Yes, Cancel"
android:textSize="14sp"
android:textAllCaps="false"
android:backgroundTint="#FF5252"
android:textColor="@android:color/white" />
</LinearLayout>
</LinearLayout>
<?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="24dp">
<!-- Title -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Terms &amp; Conditions"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginBottom="16dp"
android:gravity="center"/>
<!-- Scrollable Terms Content -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam aliquet tempor massa et ullamcorper. Nullam in pulvinar odio. Sed vitae neque ac neque bibendum bibendum at id felis. Morbi nec mi sagittis, malesuada ex vitae neque ac neque bibendum bibendum neque. Sed elementum tellus libero, sit amet tempus nibh. In porttitor congue sapien rhoncus ultrices placerat. Phasellus ut tempus orci euismod et. Curabitur ultrices tempus, viverra diam at, efficitur orci. Nullam porttitor, auctor at imperdiet. Cras porta semper felis. Fermentum ante interdum quis. Donec bibendum ultrices sapien at pretium. Donec fermentum fermentum dignissim. Maecenas accumsan a felis quis fermentum.\n\nDonec vitae accumsan metus. Etiam tempus vitae dui vel aliquam. Sed ac faucibus odio, eget vulputate nunc. Morbi posuere sem eros, et viverra justo porta sit amet. Cras in tempor metus, in aliquet justo. Praesent varius mi sapien, quis facilisis erat dictum ut. Cras consequat ligula quis interdum molestie.\n\nDonec a iaculis urna, eget hendrerit massa. Sed nec nunc id neque posuere pretium. Vivamus cursus id nibh eu justo. Aenean sed tincidunt nunc, in fringilla nibh. Fusce luctus interdum justo a molestie. Nunc accumsan orci vel lectus varius, nec rhoncus felis."
android:textSize="14sp"
android:textColor="@android:color/black"
android:lineSpacingExtra="4dp"/>
</ScrollView>
</LinearLayout>
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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">
<!-- Filter Dropdowns -->
<LinearLayout
android:id="@+id/filter_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:background="@android:color/white"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/type_filter_layout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:hint="Filter Type">
<AutoCompleteTextView
android:id="@+id/type_filter_dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:text="All Type"
android:textSize="14sp"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/status_filter_layout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:hint="Filter Status">
<AutoCompleteTextView
android:id="@+id/status_filter_dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:text="Upcoming"
android:textSize="14sp"/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<!-- Search Bar -->
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/search_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:startIconDrawable="@android:drawable/ic_menu_search"
app:boxBackgroundColor="@android:color/white"
app:layout_constraintTop_toBottomOf="@id/filter_container">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/search_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Search Unit No. or Owner Name..."
android:textSize="14sp"/>
</com.google.android.material.textfield.TextInputLayout>
<!-- SwipeRefreshLayout for Pull-to-Refresh -->
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/search_layout"
app:layout_constraintBottom_toBottomOf="parent">
<!-- RecyclerView for Appointments List -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/appointments_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="80dp"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<!-- Empty State -->
<LinearLayout
android:id="@+id/empty_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No Appointments"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/darker_gray"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="You haven't made any appointments yet"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
android:layout_marginTop="8dp"/>
</LinearLayout>
<!-- Floating Action Button to Add New Appointment -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_add_appointment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:src="@android:drawable/ic_input_add"
app:tint="@android:color/white"
app:backgroundTint="@color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
android:padding="24dp"
android:background="@android:color/white">
<!-- Title -->
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Appointment Type"
android:textSize="24sp"
android:textColor="@color/black"
android:textStyle="bold"
android:layout_marginBottom="8dp" />
<!-- Subtitle -->
<TextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Choose the type of appointment you want to make"
android:textSize="14sp"
android:textColor="@color/Grey"
android:layout_marginBottom="32dp" />
<!-- ScrollView for appointment type options -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Handover Card -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_handover"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:clickable="true"
android:focusable="true"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:strokeColor="@color/colorPrimary"
app:strokeWidth="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Handover"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Schedule a handover appointment for your unit"
android:textSize="14sp"
android:textColor="@color/Grey"
android:layout_marginTop="4dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Rectification Card -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_rectification"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:clickable="true"
android:focusable="true"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:strokeColor="@android:color/transparent"
app:strokeWidth="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rectification"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Schedule a rectification appointment for defect repairs"
android:textSize="14sp"
android:textColor="@color/Grey"
android:layout_marginTop="4dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Joint Inspection Card -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_joint_inspection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:clickable="true"
android:focusable="true"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:strokeColor="@android:color/transparent"
app:strokeWidth="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Joint Inspection"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Schedule a joint inspection with the developer"
android:textSize="14sp"
android:textColor="@color/Grey"
android:layout_marginTop="4dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Viewing Card -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_viewing"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:clickable="true"
android:focusable="true"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:strokeColor="@android:color/transparent"
app:strokeWidth="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Viewing"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Schedule a viewing appointment for your unit"
android:textSize="14sp"
android:textColor="@color/Grey"
android:layout_marginTop="4dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>
<!-- Next Button -->
<Button
android:id="@+id/next_button"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="Next"
android:textSize="16sp"
android:textColor="@android:color/white"
android:backgroundTint="@color/Grey"
android:enabled="false"
android:layout_marginTop="16dp" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView
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="wrap_content"
android:layout_margin="8dp"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
app:strokeWidth="1dp"
app:strokeColor="#E0E0E0">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Header: Type Badge and Time -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<!-- Type Badge -->
<TextView
android:id="@+id/appointment_type_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Handover"
android:textColor="@android:color/white"
android:textSize="12sp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:background="@drawable/badge_handover"
android:layout_marginEnd="8dp"/>
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"/>
<!-- Time -->
<TextView
android:id="@+id/appointment_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="09:00 AM"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"/>
</LinearLayout>
<!-- Unit Number -->
<TextView
android:id="@+id/appointment_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A-3-11"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginTop="8dp"/>
<!-- Location -->
<TextView
android:id="@+id/appointment_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="John Anthony Snow"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
android:layout_marginTop="4dp"/>
<!-- Status Badge -->
<TextView
android:id="@+id/appointment_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Confirmed"
android:textColor="@android:color/white"
android:textSize="12sp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:background="@drawable/badge_confirmed"
android:layout_marginTop="8dp"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="vertical"
android:background="#F5F5F5">
<!-- Date Header (only shown for first item of each date) -->
<TextView
android:id="@+id/date_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingTop="16dp"
android:paddingBottom="8dp"
android:text="Thu, 11 Apr 2025"
android:textSize="14sp"
android:textColor="#666666"
android:visibility="gone"/>
<!-- Appointment Card -->
<androidx.cardview.widget.CardView
android:id="@+id/appointment_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
app:cardBackgroundColor="@android:color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<!-- Left Section: Time and Badge -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginEnd="24dp">
<!-- Time -->
<TextView
android:id="@+id/appointment_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="02:30 PM"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#000000"
android:layout_marginBottom="8dp"/>
<!-- Type Badge -->
<TextView
android:id="@+id/appointment_type_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/badge_handover"
android:paddingHorizontal="10dp"
android:paddingVertical="3dp"
android:text="Handover"
android:textColor="@android:color/white"
android:textSize="13sp" />
</LinearLayout>
<!-- Right Section -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<!-- Unit Number -->
<TextView
android:id="@+id/appointment_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A-3-11"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#000000"
android:layout_marginBottom="4dp"/>
<!-- Type Badge and Location (on same line) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:baselineAligned="false">
<TextView
android:id="@+id/appointment_location"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="John Anthony Snow"
android:textSize="14sp"
android:textColor="#666666"
android:maxLines="1"
android:ellipsize="end"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment