Commit 779cb00d authored by Syazmin's avatar Syazmin

Appointment Details and Listing Done

parent ecd23c3b
......@@ -19,6 +19,7 @@ public class AppointmentAdapterNew extends RecyclerView.Adapter<AppointmentAdapt
private List<AppointmentEntity> appointments = new ArrayList<>();
private final OnAppointmentClickListener listener;
private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("EEE, d MMM yyyy", Locale.getDefault());
private boolean isCalendarView = false; // Flag to determine which layout to use
public interface OnAppointmentClickListener {
void onAppointmentClick(AppointmentEntity appointment);
......@@ -28,12 +29,18 @@ public class AppointmentAdapterNew extends RecyclerView.Adapter<AppointmentAdapt
this.listener = listener;
}
public void setCalendarView(boolean isCalendarView) {
this.isCalendarView = isCalendarView;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
int layoutId = isCalendarView ? R.layout.item_appointment_calendar : R.layout.item_appointment_new;
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_appointment_new, parent, false);
return new ViewHolder(view);
.inflate(layoutId, parent, false);
return new ViewHolder(view, isCalendarView);
}
@Override
......@@ -41,12 +48,36 @@ public class AppointmentAdapterNew extends RecyclerView.Adapter<AppointmentAdapt
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));
boolean showDateHeader = position == 0 || !isSameDate(appointments.get(position - 1), appointment);
LocalDate date = LocalDate.ofEpochDay(appointment.getSelectedDate());
if (isCalendarView) {
// Calendar view: date on LEFT
if (holder.dateHeaderContainer != null && holder.dateSpacer != null) {
if (showDateHeader) {
holder.dateHeaderContainer.setVisibility(View.VISIBLE);
holder.dateSpacer.setVisibility(View.GONE);
if (holder.dateDay != null) {
holder.dateDay.setText(String.valueOf(date.getDayOfMonth()));
}
if (holder.dateWeekday != null) {
holder.dateWeekday.setText(date.format(DateTimeFormatter.ofPattern("EEE", Locale.getDefault())));
}
} else {
holder.dateHeaderContainer.setVisibility(View.GONE);
holder.dateSpacer.setVisibility(View.VISIBLE);
}
}
} else {
holder.dateHeader.setVisibility(View.GONE);
// List view: date header at TOP
if (holder.dateHeader != null) {
if (showDateHeader) {
holder.dateHeader.setVisibility(View.VISIBLE);
holder.dateHeader.setText(date.format(dateFormatter));
} else {
holder.dateHeader.setVisibility(View.GONE);
}
}
}
// Set time
......@@ -67,17 +98,22 @@ public class AppointmentAdapterNew extends RecyclerView.Adapter<AppointmentAdapt
String type = appointment.getAppointmentType();
holder.typeBadge.setText(type);
// Set badge background based on type
// Set badge background and color bar based on type
if (type.equals("Handover")) {
holder.typeBadge.setBackgroundResource(R.drawable.badge_handover);
holder.colorBar.setBackgroundColor(0xFF0E7392); // Teal
} else if (type.equals("Rectification")) {
holder.typeBadge.setBackgroundResource(R.drawable.badge_rectification);
holder.colorBar.setBackgroundColor(0xFFFF6B35); // Orange
} else if (type.equals("Joint Inspection")) {
holder.typeBadge.setBackgroundResource(R.drawable.badge_joint_inspection);
holder.colorBar.setBackgroundColor(0xFFD32F2F); // Red
} else if (type.equals("Viewing")) {
holder.typeBadge.setBackgroundResource(R.drawable.badge_confirmed);
holder.colorBar.setBackgroundColor(0xFF4CAF50); // Green
} else {
holder.typeBadge.setBackgroundResource(R.drawable.badge_handover);
holder.colorBar.setBackgroundColor(0xFF0E7392); // Teal
}
// Click listener
......@@ -99,19 +135,42 @@ public class AppointmentAdapterNew extends RecyclerView.Adapter<AppointmentAdapt
}
static class ViewHolder extends RecyclerView.ViewHolder {
// Calendar view fields (date on LEFT)
View dateHeaderContainer;
TextView dateDay;
TextView dateWeekday;
View dateSpacer;
// List view fields (date at TOP)
TextView dateHeader;
// Common fields
TextView time;
TextView unit;
TextView typeBadge;
TextView location;
View colorBar;
ViewHolder(View itemView) {
ViewHolder(View itemView, boolean isCalendarView) {
super(itemView);
dateHeader = itemView.findViewById(R.id.date_header);
if (isCalendarView) {
// Calendar view layout
dateHeaderContainer = itemView.findViewById(R.id.date_header_container);
dateDay = itemView.findViewById(R.id.date_day);
dateWeekday = itemView.findViewById(R.id.date_weekday);
dateSpacer = itemView.findViewById(R.id.date_spacer);
} else {
// List view layout
dateHeader = itemView.findViewById(R.id.date_header);
}
// Common fields
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);
colorBar = itemView.findViewById(R.id.appointment_color_bar);
}
}
}
......@@ -13,7 +13,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialog;
public class AppointmentListActivity extends AppCompatActivity {
private ImageButton backButton;
private ImageButton filterButton;
private ImageButton toggleViewButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
......@@ -21,7 +21,7 @@ public class AppointmentListActivity extends AppCompatActivity {
setContentView(R.layout.activity_appointment_list);
backButton = findViewById(R.id.back_button);
filterButton = findViewById(R.id.filter_button);
toggleViewButton = findViewById(R.id.toggle_view_button);
// Load the appointment list fragment
if (savedInstanceState == null) {
......@@ -41,8 +41,14 @@ public class AppointmentListActivity extends AppCompatActivity {
}
});
// Filter button - Can be used for additional sorting options if needed
filterButton.setOnClickListener(v -> showFilterDialog());
// Toggle view button - switch between calendar and list view
toggleViewButton.setOnClickListener(v -> {
AppointmentListFragmentNew fragment = (AppointmentListFragmentNew) getSupportFragmentManager()
.findFragmentById(R.id.fragment_container_list);
if (fragment != null) {
fragment.toggleView();
}
});
}
private void showFilterDialog() {
......
......@@ -9,22 +9,27 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.android.material.chip.Chip;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.textfield.TextInputEditText;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
......@@ -36,7 +41,13 @@ public class AppointmentListFragmentNew extends Fragment {
private SwipeRefreshLayout swipeRefresh;
private AutoCompleteTextView typeFilterDropdown;
private AutoCompleteTextView statusFilterDropdown;
private TextInputEditText searchInput;
private LinearLayout calendarDaysContainer;
private Chip chipConfirmed, chipAttended, chipHandedOver;
private View calendarViewContainer;
private View listViewContainer;
private View statusBadgesContainer;
private View searchLayout;
private com.google.android.material.textfield.TextInputEditText searchInput;
private AppointmentDatabase db;
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
......@@ -44,6 +55,9 @@ public class AppointmentListFragmentNew extends Fragment {
private List<AppointmentEntity> allAppointments = new ArrayList<>();
private String currentTypeFilter = "All Type";
private String currentStatusFilter = "Upcoming";
private LocalDate selectedDate = null;
private boolean isCalendarViewMode = true; // Start with calendar visible
private String searchText = ""; // Store search text
private static final String STATE_TYPE_FILTER = "type_filter";
private static final String STATE_STATUS_FILTER = "status_filter";
......@@ -71,9 +85,14 @@ public class AppointmentListFragmentNew extends Fragment {
// Initialize views
recyclerView = view.findViewById(R.id.appointments_recycler_view);
fabAddAppointment = view.findViewById(R.id.fab_add_appointment);
swipeRefresh = view.findViewById(R.id.swipe_refresh);
swipeRefresh = view.findViewById(R.id.list_view_container);
typeFilterDropdown = view.findViewById(R.id.type_filter_dropdown);
statusFilterDropdown = view.findViewById(R.id.status_filter_dropdown);
calendarDaysContainer = view.findViewById(R.id.calendar_days_container);
calendarViewContainer = view.findViewById(R.id.calendar_view_container);
listViewContainer = view.findViewById(R.id.list_view_container);
statusBadgesContainer = view.findViewById(R.id.status_badges_container);
searchLayout = view.findViewById(R.id.search_layout);
searchInput = view.findViewById(R.id.search_input);
// Setup type filter dropdown
......@@ -116,13 +135,21 @@ public class AppointmentListFragmentNew extends Fragment {
filterAndDisplayAppointments();
});
// Setup search
// Initialize calendar
chipConfirmed = view.findViewById(R.id.chip_confirmed);
chipAttended = view.findViewById(R.id.chip_attended);
chipHandedOver = view.findViewById(R.id.chip_handed_over);
setupCalendar();
// Setup search input
searchInput.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) {
searchText = s.toString();
filterAndDisplayAppointments();
}
......@@ -130,11 +157,11 @@ public class AppointmentListFragmentNew extends Fragment {
public void afterTextChanged(Editable s) {}
});
// Setup SwipeRefreshLayout
// Setup SwipeRefreshLayout for List View
swipeRefresh.setColorSchemeResources(R.color.colorPrimary);
swipeRefresh.setOnRefreshListener(this::loadAllAppointments);
// Setup RecyclerView
// Setup RecyclerView for List View
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
adapter = new AppointmentAdapterNew(appointment -> {
// Handle appointment click - navigate to details
......@@ -145,6 +172,7 @@ public class AppointmentListFragmentNew extends Fragment {
.addToBackStack(null)
.commit();
});
adapter.setCalendarView(isCalendarViewMode); // Set initial view mode
recyclerView.setAdapter(adapter);
// FAB to create new appointment
......@@ -169,9 +197,61 @@ public class AppointmentListFragmentNew extends Fragment {
});
}
public void toggleView() {
isCalendarViewMode = !isCalendarViewMode;
if (isCalendarViewMode) {
// Calendar view mode
calendarViewContainer.setVisibility(View.VISIBLE);
statusBadgesContainer.setVisibility(View.GONE); // Hide badges in calendar view too
searchLayout.setVisibility(View.GONE);
searchText = ""; // Clear search when switching to calendar view
} else {
// List view mode
calendarViewContainer.setVisibility(View.GONE);
statusBadgesContainer.setVisibility(View.GONE);
searchLayout.setVisibility(View.VISIBLE);
selectedDate = null; // Clear date selection when hiding calendar
}
// Recreate adapter with correct layout
adapter = new AppointmentAdapterNew(appointment -> {
// Handle appointment click - navigate to details
AppointmentDetailsFragment detailsFragment = AppointmentDetailsFragment.newInstance(appointment.getId());
requireActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container_list, detailsFragment)
.addToBackStack(null)
.commit();
});
adapter.setCalendarView(isCalendarViewMode);
recyclerView.setAdapter(adapter);
// List is always visible
listViewContainer.setVisibility(View.VISIBLE);
// Refresh appointments display
filterAndDisplayAppointments();
}
private void filterAndDisplayAppointments() {
List<AppointmentEntity> filtered = new ArrayList<>(allAppointments);
// Filter by search text (only in list view)
if (!isCalendarViewMode && searchText != null && !searchText.trim().isEmpty()) {
String search = searchText.toLowerCase().trim();
filtered.removeIf(appointment ->
!appointment.getUnitNo().toLowerCase().contains(search) &&
!appointment.getRepresentativeName().toLowerCase().contains(search)
);
}
// Filter by selected date from calendar (only in calendar view)
if (isCalendarViewMode && selectedDate != null) {
long selectedEpochDay = selectedDate.toEpochDay();
filtered.removeIf(appointment -> appointment.getSelectedDate() != selectedEpochDay);
}
// Filter by type
if (!currentTypeFilter.equals("All Type")) {
filtered.removeIf(appointment -> !appointment.getAppointmentType().equals(currentTypeFilter));
......@@ -193,20 +273,12 @@ public class AppointmentListFragmentNew extends Fragment {
}
// If "All", don't filter by status - show everything
// Filter by search text
String searchText = searchInput.getText().toString().trim().toLowerCase();
if (!searchText.isEmpty()) {
filtered.removeIf(appointment ->
!appointment.getUnitNo().toLowerCase().contains(searchText) &&
!appointment.getLocation().toLowerCase().contains(searchText)
);
}
// Sort by date, then by time
Collections.sort(filtered, Comparator
.comparingLong(AppointmentEntity::getSelectedDate)
.thenComparing(AppointmentEntity::getSelectedTime));
// Update adapter
adapter.setAppointments(filtered);
}
......@@ -222,9 +294,6 @@ public class AppointmentListFragmentNew extends Fragment {
super.onSaveInstanceState(outState);
outState.putString(STATE_TYPE_FILTER, currentTypeFilter);
outState.putString(STATE_STATUS_FILTER, currentStatusFilter);
if (searchInput != null) {
outState.putString(STATE_SEARCH_TEXT, searchInput.getText().toString());
}
}
@Override
......@@ -238,6 +307,52 @@ public class AppointmentListFragmentNew extends Fragment {
loadAllAppointments();
}
private void setupCalendar() {
// Generate 60 days (30 before and 30 after today)
LocalDate today = LocalDate.now();
for (int i = -30; i <= 30; i++) {
LocalDate date = today.plusDays(i);
View dayView = LayoutInflater.from(requireContext()).inflate(R.layout.calendar_day_item, calendarDaysContainer, false);
TextView dateNumber = dayView.findViewById(R.id.date_number);
View selectionBackground = dayView.findViewById(R.id.selection_background);
dateNumber.setText(String.valueOf(date.getDayOfMonth()));
// Handle selection
dayView.setOnClickListener(v -> {
// Clear previous selection
for (int j = 0; j < calendarDaysContainer.getChildCount(); j++) {
View child = calendarDaysContainer.getChildAt(j);
child.findViewById(R.id.selection_background).setVisibility(View.GONE);
TextView textView = child.findViewById(R.id.date_number);
textView.setTextColor(ContextCompat.getColor(requireContext(), android.R.color.black));
}
// Set new selection
selectedDate = date;
selectionBackground.setVisibility(View.VISIBLE);
dateNumber.setTextColor(ContextCompat.getColor(requireContext(), android.R.color.white));
// Filter appointments
filterAndDisplayAppointments();
});
calendarDaysContainer.addView(dayView);
}
// Auto-scroll to today (position 30)
calendarDaysContainer.post(() -> {
View todayView = calendarDaysContainer.getChildAt(30);
if (todayView != null) {
HorizontalScrollView scrollView = (HorizontalScrollView) calendarDaysContainer.getParent();
int scrollX = todayView.getLeft() - (scrollView.getWidth() / 2) + (todayView.getWidth() / 2);
scrollView.smoothScrollTo(scrollX, 0);
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
......
package com.example.qmsmakeappointment;
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.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import java.time.LocalDate;
import java.time.format.TextStyle;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class CalendarDayAdapter extends RecyclerView.Adapter<CalendarDayAdapter.DayViewHolder> {
private List<LocalDate> dates = new ArrayList<>();
private LocalDate selectedDate = null;
private OnDateSelectedListener listener;
public interface OnDateSelectedListener {
void onDateSelected(LocalDate date);
}
public CalendarDayAdapter(OnDateSelectedListener listener) {
this.listener = listener;
}
public void setDates(List<LocalDate> dates) {
this.dates = dates;
notifyDataSetChanged();
}
public void setSelectedDate(LocalDate date) {
this.selectedDate = date;
notifyDataSetChanged();
}
@NonNull
@Override
public DayViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.calendar_day_item, parent, false);
return new DayViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull DayViewHolder holder, int position) {
LocalDate date = dates.get(position);
holder.bind(date, selectedDate != null && selectedDate.equals(date));
}
@Override
public int getItemCount() {
return dates.size();
}
class DayViewHolder extends RecyclerView.ViewHolder {
TextView dateNumber;
View selectionBackground;
DayViewHolder(@NonNull View itemView) {
super(itemView);
dateNumber = itemView.findViewById(R.id.date_number);
selectionBackground = itemView.findViewById(R.id.selection_background);
}
void bind(LocalDate date, boolean isSelected) {
// Set date number
dateNumber.setText(String.valueOf(date.getDayOfMonth()));
// Handle selection
if (isSelected) {
selectionBackground.setVisibility(View.VISIBLE);
dateNumber.setTextColor(Color.WHITE);
} else {
selectionBackground.setVisibility(View.GONE);
dateNumber.setTextColor(Color.BLACK);
}
// Click listener
itemView.setOnClickListener(v -> {
if (listener != null) {
listener.onDateSelected(date);
}
});
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/colorPrimary"/>
<size android:width="40dp" android:height="40dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M3,6h18v2H3V6zM3,11h18v2H3V11zM3,16h18v2H3V16z"/>
</vector>
......@@ -42,13 +42,13 @@
app:layout_constraintBottom_toBottomOf="parent"/>
<ImageButton
android:id="@+id/filter_button"
android:id="@+id/toggle_view_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"
android:contentDescription="Toggle View"
android:src="@drawable/ic_menu_hamburger"
app:tint="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
......
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:padding="4dp">
<!-- Background circle for selected date -->
<View
android:id="@+id/selection_background"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:background="@drawable/calendar_day_selected"
android:visibility="gone"/>
<!-- Date number -->
<TextView
android:id="@+id/day_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="15"
android:textSize="16sp"
android:textColor="@android:color/black"
android:textStyle="bold"/>
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:padding="4dp"
android:layout_marginHorizontal="2dp">
<!-- Date number with background circle -->
<FrameLayout
android:layout_width="40dp"
android:layout_height="40dp">
<!-- Selection background -->
<View
android:id="@+id/selection_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/calendar_day_selected"
android:visibility="gone"/>
<!-- Date number -->
<TextView
android:id="@+id/date_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="7"
android:textSize="16sp"
android:textColor="@android:color/black"
android:textStyle="bold"/>
</FrameLayout>
</LinearLayout>
......@@ -6,81 +6,265 @@
android:layout_height="match_parent"
android:background="#F5F5F5">
<!-- Filter Dropdowns -->
<!-- Top Bar with Filters and Toggle Button -->
<LinearLayout
android:id="@+id/filter_container"
android:id="@+id/top_bar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:background="@android:color/white"
android:gravity="center_vertical"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/type_filter_layout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
<!-- Filter Dropdowns Container -->
<LinearLayout
android:id="@+id/filter_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:hint="Filter Type">
android:orientation="horizontal">
<AutoCompleteTextView
android:id="@+id/type_filter_dropdown"
android:layout_width="match_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:inputType="none"
android:text="All Type"
android:textSize="14sp"/>
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:hint="Filter Type">
</com.google.android.material.textfield.TextInputLayout>
<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
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">
</com.google.android.material.textfield.TextInputLayout>
<AutoCompleteTextView
android:id="@+id/status_filter_dropdown"
android:layout_width="match_parent"
<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:inputType="none"
android:text="Upcoming"
android:textSize="14sp"/>
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>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</LinearLayout>
<!-- Search Bar -->
<!-- Search Bar (only visible in List View) -->
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/search_layout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:hint="Search Unit No. or Owner Name..."
android:visibility="gone"
app:startIconDrawable="@android:drawable/ic_menu_search"
app:boxBackgroundColor="@android:color/white"
app:layout_constraintTop_toBottomOf="@id/filter_container">
app:layout_constraintTop_toBottomOf="@id/top_bar_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"/>
android:inputType="text"
android:maxLines="1"/>
</com.google.android.material.textfield.TextInputLayout>
<!-- SwipeRefreshLayout for Pull-to-Refresh -->
<!-- Status Badge Chips (only visible in Calendar View) -->
<HorizontalScrollView
android:id="@+id/status_badges_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:background="@android:color/white"
android:paddingVertical="12dp"
android:paddingHorizontal="16dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/search_layout">
<com.google.android.material.chip.ChipGroup
android:id="@+id/status_chip_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:singleSelection="false">
<com.google.android.material.chip.Chip
android:id="@+id/chip_confirmed"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Confirmed"
android:checkable="true"
android:checked="true"
app:chipBackgroundColor="@color/colorPrimary"
app:chipIcon="@android:drawable/checkbox_on_background"
app:chipIconTint="@android:color/white"
android:textColor="@android:color/white"/>
<com.google.android.material.chip.Chip
android:id="@+id/chip_attended"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Attended"
android:checkable="true"
android:checked="true"
app:chipBackgroundColor="#4CAF50"
app:chipIcon="@android:drawable/checkbox_on_background"
app:chipIconTint="@android:color/white"
android:textColor="@android:color/white"/>
<com.google.android.material.chip.Chip
android:id="@+id/chip_handed_over"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Handed Over"
android:checkable="true"
android:checked="true"
app:chipBackgroundColor="@color/colorPrimary"
app:chipIcon="@android:drawable/checkbox_on_background"
app:chipIconTint="@android:color/white"
android:textColor="@android:color/white"/>
</com.google.android.material.chip.ChipGroup>
</HorizontalScrollView>
<!-- Horizontal Scrollable Calendar -->
<LinearLayout
android:id="@+id/calendar_view_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@android:color/white"
android:visibility="visible"
android:paddingVertical="12dp"
app:layout_constraintTop_toBottomOf="@id/status_badges_container">
<!-- Day Headers (Sun Mon Tue Wed Thu Fri Sat) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="8dp"
android:paddingBottom="8dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Sun"
android:textAlignment="center"
android:textSize="12sp"
android:textStyle="bold"
android:textColor="#666666"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Mon"
android:textAlignment="center"
android:textSize="12sp"
android:textStyle="bold"
android:textColor="#666666"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Tue"
android:textAlignment="center"
android:textSize="12sp"
android:textStyle="bold"
android:textColor="#666666"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Wed"
android:textAlignment="center"
android:textSize="12sp"
android:textStyle="bold"
android:textColor="#666666"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Thu"
android:textAlignment="center"
android:textSize="12sp"
android:textStyle="bold"
android:textColor="#666666"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Fri"
android:textAlignment="center"
android:textSize="12sp"
android:textStyle="bold"
android:textColor="#666666"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Sat"
android:textAlignment="center"
android:textSize="12sp"
android:textStyle="bold"
android:textColor="#666666"/>
</LinearLayout>
<!-- Horizontal Calendar Row (ONE WEEK at a time) -->
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:id="@+id/calendar_days_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="8dp"/>
</HorizontalScrollView>
</LinearLayout>
<!-- Appointments List -->
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:id="@+id/list_view_container"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/search_layout"
android:visibility="visible"
app:layout_constraintTop_toBottomOf="@id/calendar_view_container"
app:layout_constraintBottom_toBottomOf="parent">
<!-- RecyclerView for Appointments List -->
......
<?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="horizontal"
android:background="#F5F5F5"
android:paddingVertical="4dp">
<!-- Date Header on LEFT (only shown for first item of each date) -->
<LinearLayout
android:id="@+id/date_header_container"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:paddingHorizontal="8dp"
android:paddingTop="8dp"
android:visibility="gone">
<TextView
android:id="@+id/date_day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="11"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="#000000"/>
<TextView
android:id="@+id/date_weekday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Thu"
android:textSize="12sp"
android:textColor="#666666"/>
</LinearLayout>
<!-- Spacer when no date header -->
<View
android:id="@+id/date_spacer"
android:layout_width="60dp"
android:layout_height="1dp"
android:visibility="visible"/>
<!-- Appointment Card -->
<androidx.cardview.widget.CardView
android:id="@+id/appointment_card"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="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">
<!-- Colored Left Border -->
<View
android:id="@+id/appointment_color_bar"
android:layout_width="4dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary"/>
<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"/>
<!-- Owner Name -->
<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>
......@@ -6,7 +6,7 @@
android:orientation="vertical"
android:background="#F5F5F5">
<!-- Date Header (only shown for first item of each date) -->
<!-- Date Header at TOP (only shown for first item of each date) -->
<TextView
android:id="@+id/date_header"
android:layout_width="match_parent"
......@@ -33,8 +33,20 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
android:orientation="horizontal">
<!-- Colored Left Border -->
<View
android:id="@+id/appointment_color_bar"
android:layout_width="4dp"
android:layout_height="match_parent"
android:background="@color/colorPrimary"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<!-- Left Section: Time and Badge -->
<LinearLayout
......@@ -112,6 +124,8 @@
</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