Implemented View Binding to reduce code
- project uses view binding now so we don have to do getViewbyId to refer to the xml
This commit is contained in:
@@ -39,6 +39,7 @@ android {
|
|||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
buildConfig = true
|
buildConfig = true
|
||||||
|
viewBinding = true
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|||||||
@@ -20,14 +20,14 @@ import androidx.navigation.fragment.NavHostFragment;
|
|||||||
import androidx.navigation.ui.NavigationUI;
|
import androidx.navigation.ui.NavigationUI;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
|
import com.example.petstoremobile.databinding.ActivityHomeBinding;
|
||||||
import com.example.petstoremobile.services.ChatNotificationService;
|
import com.example.petstoremobile.services.ChatNotificationService;
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
|
||||||
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class HomeActivity extends AppCompatActivity {
|
public class HomeActivity extends AppCompatActivity {
|
||||||
private BottomNavigationView bottomNav;
|
private ActivityHomeBinding binding;
|
||||||
private NavController navController;
|
private NavController navController;
|
||||||
|
|
||||||
// Launcher to ask for notification permission
|
// Launcher to ask for notification permission
|
||||||
@@ -45,23 +45,21 @@ public class HomeActivity extends AppCompatActivity {
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
EdgeToEdge.enable(this);
|
EdgeToEdge.enable(this);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_home);
|
binding = ActivityHomeBinding.inflate(getLayoutInflater());
|
||||||
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
ViewCompat.setOnApplyWindowInsetsListener(binding.main, (v, insets) -> {
|
||||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
|
||||||
//get the bottom navbar from the layout
|
|
||||||
bottomNav = findViewById(R.id.bottom_navigation);
|
|
||||||
|
|
||||||
// Initialize Navigation Component
|
// Initialize Navigation Component
|
||||||
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager()
|
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager()
|
||||||
.findFragmentById(R.id.nav_host_fragment);
|
.findFragmentById(R.id.nav_host_fragment);
|
||||||
if (navHostFragment != null) {
|
if (navHostFragment != null) {
|
||||||
navController = navHostFragment.getNavController();
|
navController = navHostFragment.getNavController();
|
||||||
NavigationUI.setupWithNavController(bottomNav, navController);
|
NavigationUI.setupWithNavController(binding.bottomNavigation, navController);
|
||||||
}
|
}
|
||||||
|
|
||||||
//load the list fragment by default if it's a fresh start
|
//load the list fragment by default if it's a fresh start
|
||||||
@@ -89,9 +87,9 @@ public class HomeActivity extends AppCompatActivity {
|
|||||||
*/
|
*/
|
||||||
private void handleIntent(Intent intent) {
|
private void handleIntent(Intent intent) {
|
||||||
if (intent != null && "chat".equals(intent.getStringExtra("navigate_to"))) {
|
if (intent != null && "chat".equals(intent.getStringExtra("navigate_to"))) {
|
||||||
if (bottomNav != null) {
|
if (binding.bottomNavigation != null) {
|
||||||
// Navigate by selecting the bottom nav item.
|
// Navigate by selecting the bottom nav item.
|
||||||
bottomNav.setSelectedItemId(R.id.nav_chat);
|
binding.bottomNavigation.setSelectedItemId(R.id.nav_chat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,7 @@ package com.example.petstoremobile.activities;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
import androidx.activity.EdgeToEdge;
|
||||||
@@ -16,8 +12,8 @@ import androidx.core.view.ViewCompat;
|
|||||||
import androidx.core.view.WindowInsetsCompat;
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
|
||||||
import com.example.petstoremobile.api.auth.TokenManager;
|
import com.example.petstoremobile.api.auth.TokenManager;
|
||||||
|
import com.example.petstoremobile.databinding.ActivityMainBinding;
|
||||||
import com.example.petstoremobile.viewmodels.AuthViewModel;
|
import com.example.petstoremobile.viewmodels.AuthViewModel;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
|
|
||||||
@@ -30,10 +26,7 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private EditText etUser;
|
private ActivityMainBinding binding;
|
||||||
private EditText etPassword;
|
|
||||||
private Button btnLogin;
|
|
||||||
private TextView tvLoginStatus;
|
|
||||||
private AuthViewModel viewModel;
|
private AuthViewModel viewModel;
|
||||||
|
|
||||||
@Inject TokenManager tokenManager;
|
@Inject TokenManager tokenManager;
|
||||||
@@ -59,41 +52,38 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setContentView(R.layout.activity_main);
|
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||||
|
setContentView(binding.getRoot());
|
||||||
|
viewModel = new ViewModelProvider(this).get(AuthViewModel.class);
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
ViewCompat.setOnApplyWindowInsetsListener(binding.main, (v, insets) -> {
|
||||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
|
||||||
//get all controls from layout
|
|
||||||
tvLoginStatus = findViewById(R.id.tvLoginStatus);
|
|
||||||
etUser = findViewById(R.id.etUser);
|
|
||||||
etPassword = findViewById(R.id.etPassword);
|
|
||||||
btnLogin = findViewById(R.id.btnLogin);
|
|
||||||
//clear login status
|
//clear login status
|
||||||
tvLoginStatus.setText("");
|
binding.tvLoginStatus.setText("");
|
||||||
|
|
||||||
// Set editor action listener for password field to login on when enter is pressed
|
// Set editor action listener for password field to login on when enter is pressed
|
||||||
etPassword.setOnEditorActionListener((v, actionId, event) -> {
|
binding.etPassword.setOnEditorActionListener((v, actionId, event) -> {
|
||||||
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
|
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
|
||||||
btnLogin.performClick();
|
binding.btnLogin.performClick();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
//Set click listener for login button
|
//Set click listener for login button
|
||||||
btnLogin.setOnClickListener(v -> {
|
binding.btnLogin.setOnClickListener(v -> {
|
||||||
//Get username and password from text fields
|
//Get username and password from text fields
|
||||||
String username = etUser.getText().toString();
|
String username = binding.etUser.getText().toString();
|
||||||
String password = etPassword.getText().toString();
|
String password = binding.etPassword.getText().toString();
|
||||||
|
|
||||||
//check if fields are empty
|
//check if fields are empty
|
||||||
if (username.isEmpty() || password.isEmpty()) {
|
if (username.isEmpty() || password.isEmpty()) {
|
||||||
Toast.makeText(this, "Please enter username and password", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Please enter username and password", Toast.LENGTH_SHORT).show();
|
||||||
tvLoginStatus.setText("Please enter username and password");
|
binding.tvLoginStatus.setText("Please enter username and password");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,15 +100,15 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
switch (resource.status) {
|
switch (resource.status) {
|
||||||
case LOADING:
|
case LOADING:
|
||||||
btnLogin.setEnabled(false);
|
binding.btnLogin.setEnabled(false);
|
||||||
tvLoginStatus.setText("Logging in...");
|
binding.tvLoginStatus.setText("Logging in...");
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
if (resource.data != null) {
|
if (resource.data != null) {
|
||||||
String role = resource.data.getRole();
|
String role = resource.data.getRole();
|
||||||
if ("CUSTOMER".equalsIgnoreCase(role)) {
|
if ("CUSTOMER".equalsIgnoreCase(role)) {
|
||||||
btnLogin.setEnabled(true);
|
binding.btnLogin.setEnabled(true);
|
||||||
tvLoginStatus.setText("Customers are not allowed to log in");
|
binding.tvLoginStatus.setText("Customers are not allowed to log in");
|
||||||
Toast.makeText(this, "Access denied: Customers are not allowed to log in.", Toast.LENGTH_LONG).show();
|
Toast.makeText(this, "Access denied: Customers are not allowed to log in.", Toast.LENGTH_LONG).show();
|
||||||
} else {
|
} else {
|
||||||
tokenManager.saveLoginData(resource.data.getToken(), resource.data.getUsername(), role);
|
tokenManager.saveLoginData(resource.data.getToken(), resource.data.getUsername(), role);
|
||||||
@@ -127,8 +117,8 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
btnLogin.setEnabled(true);
|
binding.btnLogin.setEnabled(true);
|
||||||
tvLoginStatus.setText(resource.message);
|
binding.tvLoginStatus.setText(resource.message);
|
||||||
Toast.makeText(this, resource.message, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, resource.message, Toast.LENGTH_LONG).show();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,12 @@ import android.provider.OpenableColumns;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.widget.*;
|
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
import androidx.activity.result.contract.ActivityResultContracts;
|
import androidx.activity.result.contract.ActivityResultContracts;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.view.GravityCompat;
|
import androidx.core.view.GravityCompat;
|
||||||
import androidx.drawerlayout.widget.DrawerLayout;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.ChatAdapter;
|
import com.example.petstoremobile.adapters.ChatAdapter;
|
||||||
@@ -26,10 +23,10 @@ import com.example.petstoremobile.api.auth.TokenManager;
|
|||||||
import com.example.petstoremobile.api.ChatApi;
|
import com.example.petstoremobile.api.ChatApi;
|
||||||
import com.example.petstoremobile.api.CustomerApi;
|
import com.example.petstoremobile.api.CustomerApi;
|
||||||
import com.example.petstoremobile.api.MessageApi;
|
import com.example.petstoremobile.api.MessageApi;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentChatBinding;
|
||||||
import com.example.petstoremobile.dtos.ConversationDTO;
|
import com.example.petstoremobile.dtos.ConversationDTO;
|
||||||
import com.example.petstoremobile.dtos.CustomerDTO;
|
import com.example.petstoremobile.dtos.CustomerDTO;
|
||||||
import com.example.petstoremobile.dtos.MessageDTO;
|
import com.example.petstoremobile.dtos.MessageDTO;
|
||||||
import com.example.petstoremobile.dtos.PageResponse;
|
|
||||||
import com.example.petstoremobile.dtos.SendMessageRequest;
|
import com.example.petstoremobile.dtos.SendMessageRequest;
|
||||||
import com.example.petstoremobile.models.Chat;
|
import com.example.petstoremobile.models.Chat;
|
||||||
import com.example.petstoremobile.models.Message;
|
import com.example.petstoremobile.models.Message;
|
||||||
@@ -44,7 +41,6 @@ import javax.inject.Inject;
|
|||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
import retrofit2.*;
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickListener, StompChatManager.MessageListener,
|
public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickListener, StompChatManager.MessageListener,
|
||||||
@@ -52,19 +48,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
|
|
||||||
private static final String TAG = "ChatFragment";
|
private static final String TAG = "ChatFragment";
|
||||||
|
|
||||||
// View
|
private FragmentChatBinding binding;
|
||||||
private DrawerLayout drawerLayout;
|
|
||||||
private RecyclerView rvChatList, rvMessages;
|
|
||||||
private EditText etMessage;
|
|
||||||
private Button btnSend;
|
|
||||||
private ImageButton btnAttach;
|
|
||||||
private TextView tvChatTitle;
|
|
||||||
|
|
||||||
// Preview views
|
|
||||||
private View layoutAttachmentPreview;
|
|
||||||
private ImageView ivPreview;
|
|
||||||
private TextView tvPreviewName;
|
|
||||||
private ImageButton btnRemoveAttachment;
|
|
||||||
|
|
||||||
// Adapters
|
// Adapters
|
||||||
private ChatAdapter chatAdapter;
|
private ChatAdapter chatAdapter;
|
||||||
@@ -115,35 +99,21 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
ViewGroup container, Bundle savedInstanceState) {
|
ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
View view = inflater.inflate(R.layout.fragment_chat, container, false);
|
binding = FragmentChatBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
drawerLayout = view.findViewById(R.id.chatDrawerLayout);
|
binding.btnHamburger.setOnClickListener(v -> binding.chatDrawerLayout.openDrawer(GravityCompat.START));
|
||||||
rvChatList = view.findViewById(R.id.rvChatList);
|
|
||||||
rvMessages = view.findViewById(R.id.rvMessages);
|
|
||||||
etMessage = view.findViewById(R.id.etMessage);
|
|
||||||
btnSend = view.findViewById(R.id.btnSend);
|
|
||||||
btnAttach = view.findViewById(R.id.btnAttach);
|
|
||||||
tvChatTitle = view.findViewById(R.id.tvChatTitle);
|
|
||||||
|
|
||||||
layoutAttachmentPreview = view.findViewById(R.id.layoutAttachmentPreview);
|
|
||||||
ivPreview = view.findViewById(R.id.ivPreview);
|
|
||||||
tvPreviewName = view.findViewById(R.id.tvPreviewName);
|
|
||||||
btnRemoveAttachment = view.findViewById(R.id.btnRemoveAttachment);
|
|
||||||
|
|
||||||
ImageButton hamburger = view.findViewById(R.id.btnHamburger);
|
|
||||||
hamburger.setOnClickListener(v -> drawerLayout.openDrawer(GravityCompat.START));
|
|
||||||
|
|
||||||
// Set editor action listener for message field to send when enter is pressed
|
// Set editor action listener for message field to send when enter is pressed
|
||||||
etMessage.setOnEditorActionListener((v, actionId, event) -> {
|
binding.etMessage.setOnEditorActionListener((v, actionId, event) -> {
|
||||||
if (actionId == EditorInfo.IME_ACTION_SEND || actionId == EditorInfo.IME_NULL) {
|
if (actionId == EditorInfo.IME_ACTION_SEND || actionId == EditorInfo.IME_NULL) {
|
||||||
btnSend.performClick();
|
binding.btnSend.performClick();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
//When the send button is clicked check if there is an attachment and send using the correct helper function
|
//When the send button is clicked check if there is an attachment and send using the correct helper function
|
||||||
btnSend.setOnClickListener(v -> {
|
binding.btnSend.setOnClickListener(v -> {
|
||||||
if (pendingAttachmentUri != null) {
|
if (pendingAttachmentUri != null) {
|
||||||
sendWithAttachment(pendingAttachmentUri);
|
sendWithAttachment(pendingAttachmentUri);
|
||||||
} else {
|
} else {
|
||||||
@@ -152,13 +122,13 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
});
|
});
|
||||||
|
|
||||||
//When the attachment button is clicked open the file picker
|
//When the attachment button is clicked open the file picker
|
||||||
btnAttach.setOnClickListener(v -> selectAttachment());
|
binding.btnAttach.setOnClickListener(v -> selectAttachment());
|
||||||
btnRemoveAttachment.setOnClickListener(v -> removeAttachment());
|
binding.btnRemoveAttachment.setOnClickListener(v -> removeAttachment());
|
||||||
|
|
||||||
setupRecyclerViews();
|
setupRecyclerViews();
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -167,15 +137,15 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
private void setupRecyclerViews() {
|
private void setupRecyclerViews() {
|
||||||
// Set up Drawer menu to select conversation
|
// Set up Drawer menu to select conversation
|
||||||
chatAdapter = new ChatAdapter(chatList, this);
|
chatAdapter = new ChatAdapter(chatList, this);
|
||||||
rvChatList.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.rvChatList.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
rvChatList.setAdapter(chatAdapter);
|
binding.rvChatList.setAdapter(chatAdapter);
|
||||||
|
|
||||||
// set up RecyclerView for selected chat to show messages
|
// set up RecyclerView for selected chat to show messages
|
||||||
messageAdapter = new MessageAdapter(messageList, null);
|
messageAdapter = new MessageAdapter(messageList, null);
|
||||||
LinearLayoutManager lm = new LinearLayoutManager(getContext());
|
LinearLayoutManager lm = new LinearLayoutManager(getContext());
|
||||||
lm.setStackFromEnd(true);
|
lm.setStackFromEnd(true);
|
||||||
rvMessages.setLayoutManager(lm);
|
binding.rvMessages.setLayoutManager(lm);
|
||||||
rvMessages.setAdapter(messageAdapter);
|
binding.rvMessages.setAdapter(messageAdapter);
|
||||||
setConversationActive(false);
|
setConversationActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +217,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
// Update title to customer name of active conversation
|
// Update title to customer name of active conversation
|
||||||
for (Chat chat : chatList) {
|
for (Chat chat : chatList) {
|
||||||
if (chat.getChatId().equals(String.valueOf(activeConversationId))) {
|
if (chat.getChatId().equals(String.valueOf(activeConversationId))) {
|
||||||
tvChatTitle.setText(chat.getCustomerName());
|
binding.tvChatTitle.setText(chat.getCustomerName());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,8 +240,8 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
public void onChatClick(Chat chat) {
|
public void onChatClick(Chat chat) {
|
||||||
activeConversationId = Long.parseLong(chat.getChatId());
|
activeConversationId = Long.parseLong(chat.getChatId());
|
||||||
setConversationActive(true);
|
setConversationActive(true);
|
||||||
tvChatTitle.setText(chat.getCustomerName());
|
binding.tvChatTitle.setText(chat.getCustomerName());
|
||||||
drawerLayout.closeDrawer(GravityCompat.START);
|
binding.chatDrawerLayout.closeDrawer(GravityCompat.START);
|
||||||
|
|
||||||
if (stompChatManager != null) {
|
if (stompChatManager != null) {
|
||||||
stompChatManager.subscribeToConversation(activeConversationId);
|
stompChatManager.subscribeToConversation(activeConversationId);
|
||||||
@@ -302,11 +272,11 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
if (activeConversationId == null) return;
|
if (activeConversationId == null) return;
|
||||||
|
|
||||||
//get the message from text field
|
//get the message from text field
|
||||||
String text = etMessage.getText().toString().trim();
|
String text = binding.etMessage.getText().toString().trim();
|
||||||
if (text.isEmpty()) return;
|
if (text.isEmpty()) return;
|
||||||
|
|
||||||
//clear text field after sending
|
//clear text field after sending
|
||||||
etMessage.setText("");
|
binding.etMessage.setText("");
|
||||||
|
|
||||||
//calls api to send the message
|
//calls api to send the message
|
||||||
messageApi.sendMessage(activeConversationId, new SendMessageRequest(text))
|
messageApi.sendMessage(activeConversationId, new SendMessageRequest(text))
|
||||||
@@ -332,18 +302,18 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
*/
|
*/
|
||||||
private void showAttachmentPreview(Uri uri) {
|
private void showAttachmentPreview(Uri uri) {
|
||||||
pendingAttachmentUri = uri;
|
pendingAttachmentUri = uri;
|
||||||
layoutAttachmentPreview.setVisibility(View.VISIBLE);
|
binding.layoutAttachmentPreview.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
String mimeType = requireContext().getContentResolver().getType(uri);
|
String mimeType = requireContext().getContentResolver().getType(uri);
|
||||||
String fileName = getFileName(uri);
|
String fileName = getFileName(uri);
|
||||||
tvPreviewName.setText(fileName);
|
binding.tvPreviewName.setText(fileName);
|
||||||
|
|
||||||
// If the file is an image, display a thumbnail of the image as well
|
// If the file is an image, display a thumbnail of the image as well
|
||||||
if (mimeType != null && mimeType.startsWith("image/")) {
|
if (mimeType != null && mimeType.startsWith("image/")) {
|
||||||
ivPreview.setVisibility(View.VISIBLE);
|
binding.ivPreview.setVisibility(View.VISIBLE);
|
||||||
Glide.with(this).load(uri).into(ivPreview);
|
Glide.with(this).load(uri).into(binding.ivPreview);
|
||||||
} else {
|
} else {
|
||||||
ivPreview.setVisibility(View.GONE);
|
binding.ivPreview.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +322,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
*/
|
*/
|
||||||
private void removeAttachment() {
|
private void removeAttachment() {
|
||||||
pendingAttachmentUri = null;
|
pendingAttachmentUri = null;
|
||||||
layoutAttachmentPreview.setVisibility(View.GONE);
|
binding.layoutAttachmentPreview.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -448,7 +418,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
|
|
||||||
if (activeConversationId != null && activeConversationId.equals(dto.getId())) {
|
if (activeConversationId != null && activeConversationId.equals(dto.getId())) {
|
||||||
setConversationActive(true);
|
setConversationActive(true);
|
||||||
tvChatTitle.setText(name);
|
binding.tvChatTitle.setText(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,8 +483,8 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
*/
|
*/
|
||||||
private void scrollToBottom() {
|
private void scrollToBottom() {
|
||||||
if (!messageList.isEmpty()) {
|
if (!messageList.isEmpty()) {
|
||||||
rvMessages.post(() ->
|
binding.rvMessages.post(() ->
|
||||||
rvMessages.smoothScrollToPosition(messageList.size() - 1));
|
binding.rvMessages.smoothScrollToPosition(messageList.size() - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,23 +516,23 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
* Toggles the UI state based on whether a conversation is currently selected.
|
* Toggles the UI state based on whether a conversation is currently selected.
|
||||||
*/
|
*/
|
||||||
private void setConversationActive(boolean active) {
|
private void setConversationActive(boolean active) {
|
||||||
btnSend.setEnabled(active);
|
binding.btnSend.setEnabled(active);
|
||||||
etMessage.setEnabled(active);
|
binding.etMessage.setEnabled(active);
|
||||||
btnAttach.setEnabled(active);
|
binding.btnAttach.setEnabled(active);
|
||||||
if (!active) {
|
if (!active) {
|
||||||
activeConversationId = null;
|
activeConversationId = null;
|
||||||
ChatNotificationService.activeConversationIdInUi = null;
|
ChatNotificationService.activeConversationIdInUi = null;
|
||||||
removeAttachment();
|
removeAttachment();
|
||||||
if (tvChatTitle != null) tvChatTitle.setText("Customer Chat");
|
if (binding != null && binding.tvChatTitle != null) binding.tvChatTitle.setText("Customer Chat");
|
||||||
if (stompChatManager != null) {
|
if (stompChatManager != null) {
|
||||||
stompChatManager.clearConversationSubscription();
|
stompChatManager.clearConversationSubscription();
|
||||||
}
|
}
|
||||||
messageList.clear();
|
messageList.clear();
|
||||||
messageAdapter.notifyDataSetChanged();
|
messageAdapter.notifyDataSetChanged();
|
||||||
etMessage.setText("");
|
binding.etMessage.setText("");
|
||||||
etMessage.setHint("Select a chat to start messaging");
|
binding.etMessage.setHint("Select a chat to start messaging");
|
||||||
} else {
|
} else {
|
||||||
etMessage.setHint("Type a message...");
|
binding.etMessage.setHint("Type a message...");
|
||||||
ChatNotificationService.activeConversationIdInUi = activeConversationId;
|
ChatNotificationService.activeConversationIdInUi = activeConversationId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -573,6 +543,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
ChatNotificationService.activeConversationIdInUi = null;
|
ChatNotificationService.activeConversationIdInUi = null;
|
||||||
if (stompChatManager != null) stompChatManager.disconnect();
|
if (stompChatManager != null) stompChatManager.disconnect();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,10 @@ import android.view.LayoutInflater;
|
|||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
|
|
||||||
import com.example.petstoremobile.api.auth.TokenManager;
|
import com.example.petstoremobile.api.auth.TokenManager;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentListBinding;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@@ -28,12 +27,7 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class ListFragment extends Fragment {
|
public class ListFragment extends Fragment {
|
||||||
|
|
||||||
private DrawerLayout drawerLayout;
|
private FragmentListBinding binding;
|
||||||
private LinearLayout drawerPets, drawerServices, drawerSuppliers;
|
|
||||||
private View touchBlocker;
|
|
||||||
|
|
||||||
private LinearLayout drawerAdoptions, drawerAppointments, drawerInventory, drawerProducts, drawerProductSupplier, drawerPurchaseOrderView, drawerSale;
|
|
||||||
|
|
||||||
private NavController innerNavController;
|
private NavController innerNavController;
|
||||||
|
|
||||||
@Inject TokenManager tokenManager;
|
@Inject TokenManager tokenManager;
|
||||||
@@ -42,49 +36,33 @@ public class ListFragment extends Fragment {
|
|||||||
* Inflates the fragment layout, initializes navigation drawers, and applies role-based access control.
|
* Inflates the fragment layout, initializes navigation drawers, and applies role-based access control.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_list, container, false);
|
binding = FragmentListBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
//get controls from the layout
|
|
||||||
drawerLayout = view.findViewById(R.id.drawerLayout);
|
|
||||||
drawerPets = view.findViewById(R.id.drawerPets);
|
|
||||||
drawerServices = view.findViewById(R.id.drawerServices);
|
|
||||||
drawerSuppliers = view.findViewById(R.id.drawerSuppliers);
|
|
||||||
drawerAdoptions = view.findViewById(R.id.drawerAdoptions);
|
|
||||||
drawerAppointments = view.findViewById(R.id.drawerAppointments);
|
|
||||||
drawerInventory = view.findViewById(R.id.drawerInventory);
|
|
||||||
drawerProducts = view.findViewById(R.id.drawerProducts);
|
|
||||||
drawerProductSupplier=view.findViewById(R.id.drawerProductSupplier);
|
|
||||||
drawerSale=view.findViewById(R.id.drawerSale);
|
|
||||||
drawerPurchaseOrderView=view.findViewById(R.id.drawerPurchaseOrderView);
|
|
||||||
|
|
||||||
// Check user role and restrict access for STAFF
|
// Check user role and restrict access for STAFF
|
||||||
String role = tokenManager.getRole();
|
String role = tokenManager.getRole();
|
||||||
if ("STAFF".equalsIgnoreCase(role)) {
|
if ("STAFF".equalsIgnoreCase(role)) {
|
||||||
drawerSuppliers.setVisibility(View.GONE);
|
binding.drawerSuppliers.setVisibility(View.GONE);
|
||||||
drawerInventory.setVisibility(View.GONE);
|
binding.drawerInventory.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//needed to disable touches on the innerContainer while the drawer is open
|
|
||||||
touchBlocker = view.findViewById(R.id.touchBlocker);
|
|
||||||
|
|
||||||
//add Listeners to the drawer so user won't be able to interact with the innerContainer (the list fragments)
|
//add Listeners to the drawer so user won't be able to interact with the innerContainer (the list fragments)
|
||||||
//while the drawer is open
|
//while the drawer is open
|
||||||
drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
|
binding.drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
|
||||||
|
|
||||||
//When the drawer is opened, disable touches on the background
|
//When the drawer is opened, disable touches on the background
|
||||||
@Override
|
@Override
|
||||||
public void onDrawerOpened(View drawerView) {
|
public void onDrawerOpened(View drawerView) {
|
||||||
touchBlocker.setVisibility(View.VISIBLE);
|
binding.touchBlocker.setVisibility(View.VISIBLE);
|
||||||
touchBlocker.setClickable(true);
|
binding.touchBlocker.setClickable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//When the drawer is closed, enable touches again
|
//When the drawer is closed, enable touches again
|
||||||
@Override
|
@Override
|
||||||
public void onDrawerClosed(View drawerView) {
|
public void onDrawerClosed(View drawerView) {
|
||||||
touchBlocker.setVisibility(View.GONE);
|
binding.touchBlocker.setVisibility(View.GONE);
|
||||||
touchBlocker.setClickable(false);
|
binding.touchBlocker.setClickable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//unused methods
|
//unused methods
|
||||||
@@ -95,18 +73,24 @@ public class ListFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Click listeners for each drawer
|
// Click listeners for each drawer
|
||||||
drawerPets.setOnClickListener(v -> navigateTo(R.id.nav_pet));
|
binding.drawerPets.setOnClickListener(v -> navigateTo(R.id.nav_pet));
|
||||||
drawerServices.setOnClickListener(v -> navigateTo(R.id.nav_service));
|
binding.drawerServices.setOnClickListener(v -> navigateTo(R.id.nav_service));
|
||||||
drawerSuppliers.setOnClickListener(v -> navigateTo(R.id.nav_supplier));
|
binding.drawerSuppliers.setOnClickListener(v -> navigateTo(R.id.nav_supplier));
|
||||||
drawerAdoptions.setOnClickListener(v -> navigateTo(R.id.nav_adoption));
|
binding.drawerAdoptions.setOnClickListener(v -> navigateTo(R.id.nav_adoption));
|
||||||
drawerAppointments.setOnClickListener(v -> navigateTo(R.id.nav_appointment));
|
binding.drawerAppointments.setOnClickListener(v -> navigateTo(R.id.nav_appointment));
|
||||||
drawerInventory.setOnClickListener(v -> navigateTo(R.id.nav_inventory));
|
binding.drawerInventory.setOnClickListener(v -> navigateTo(R.id.nav_inventory));
|
||||||
drawerProducts.setOnClickListener(v -> navigateTo(R.id.nav_product));
|
binding.drawerProducts.setOnClickListener(v -> navigateTo(R.id.nav_product));
|
||||||
drawerProductSupplier.setOnClickListener(v -> navigateTo(R.id.nav_product_supplier));
|
binding.drawerProductSupplier.setOnClickListener(v -> navigateTo(R.id.nav_product_supplier));
|
||||||
drawerPurchaseOrderView.setOnClickListener(v -> navigateTo(R.id.nav_purchase_order));
|
binding.drawerPurchaseOrderView.setOnClickListener(v -> navigateTo(R.id.nav_purchase_order));
|
||||||
drawerSale.setOnClickListener(v -> navigateTo(R.id.nav_sale));
|
binding.drawerSale.setOnClickListener(v -> navigateTo(R.id.nav_sale));
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -129,13 +113,13 @@ public class ListFragment extends Fragment {
|
|||||||
if (innerNavController != null) {
|
if (innerNavController != null) {
|
||||||
innerNavController.navigate(destinationId);
|
innerNavController.navigate(destinationId);
|
||||||
}
|
}
|
||||||
drawerLayout.closeDrawers();
|
binding.drawerLayout.closeDrawers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Programmatically opens the navigation drawer.
|
* Programmatically opens the navigation drawer.
|
||||||
*/
|
*/
|
||||||
public void openDrawer() {
|
public void openDrawer() {
|
||||||
drawerLayout.openDrawer(GravityCompat.START);
|
binding.drawerLayout.openDrawer(GravityCompat.START);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.example.petstoremobile.fragments;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
@@ -10,19 +11,16 @@ import android.util.Log;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.activities.MainActivity;
|
import com.example.petstoremobile.activities.MainActivity;
|
||||||
import com.example.petstoremobile.api.auth.AuthApi;
|
import com.example.petstoremobile.api.auth.AuthApi;
|
||||||
import com.example.petstoremobile.api.auth.TokenManager;
|
import com.example.petstoremobile.api.auth.TokenManager;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentProfileBinding;
|
||||||
import com.example.petstoremobile.dtos.UserDTO;
|
import com.example.petstoremobile.dtos.UserDTO;
|
||||||
import com.example.petstoremobile.services.ChatNotificationService;
|
import com.example.petstoremobile.services.ChatNotificationService;
|
||||||
import com.example.petstoremobile.utils.ErrorUtils;
|
|
||||||
import com.example.petstoremobile.utils.FileUtils;
|
import com.example.petstoremobile.utils.FileUtils;
|
||||||
import com.example.petstoremobile.utils.GlideUtils;
|
import com.example.petstoremobile.utils.GlideUtils;
|
||||||
import com.example.petstoremobile.utils.ImagePickerHelper;
|
import com.example.petstoremobile.utils.ImagePickerHelper;
|
||||||
@@ -41,9 +39,6 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
import okhttp3.MultipartBody;
|
import okhttp3.MultipartBody;
|
||||||
import okhttp3.RequestBody;
|
import okhttp3.RequestBody;
|
||||||
import retrofit2.Call;
|
|
||||||
import retrofit2.Callback;
|
|
||||||
import retrofit2.Response;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment that displays and allows editing of the user's profile information.
|
* Fragment that displays and allows editing of the user's profile information.
|
||||||
@@ -51,9 +46,7 @@ import retrofit2.Response;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class ProfileFragment extends Fragment {
|
public class ProfileFragment extends Fragment {
|
||||||
|
|
||||||
//initialize the view/controls
|
private FragmentProfileBinding binding;
|
||||||
private ImageView imgProfile;
|
|
||||||
private TextView tvProfileName, tvProfileEmail, tvProfilePhone, tvProfileRole;
|
|
||||||
private UserDTO currentUser;
|
private UserDTO currentUser;
|
||||||
private boolean hasImage = false;
|
private boolean hasImage = false;
|
||||||
|
|
||||||
@@ -87,37 +80,26 @@ public class ProfileFragment extends Fragment {
|
|||||||
* Inflates the fragment layout and sets up listeners for profile.
|
* Inflates the fragment layout and sets up listeners for profile.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_profile, container, false);
|
binding = FragmentProfileBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
//get all the controls from the view
|
|
||||||
imgProfile = view.findViewById(R.id.imgProfile);
|
|
||||||
tvProfileName = view.findViewById(R.id.tvProfileName);
|
|
||||||
tvProfileEmail = view.findViewById(R.id.tvProfileEmail);
|
|
||||||
tvProfilePhone = view.findViewById(R.id.tvProfilePhone);
|
|
||||||
tvProfileRole = view.findViewById(R.id.tvProfileRole);
|
|
||||||
Button btnChangePhoto = view.findViewById(R.id.btnChangePhoto);
|
|
||||||
Button btnEditEmail = view.findViewById(R.id.btnEditEmail);
|
|
||||||
Button btnEditPhone = view.findViewById(R.id.btnEditPhone);
|
|
||||||
Button btnLogout = view.findViewById(R.id.btnLogout);
|
|
||||||
|
|
||||||
//Load Profile Data from backend
|
//Load Profile Data from backend
|
||||||
loadProfileData();
|
loadProfileData();
|
||||||
|
|
||||||
//Set up listeners for the buttons
|
//Set up listeners for the buttons
|
||||||
//Change photo button
|
//Change photo button
|
||||||
btnChangePhoto.setOnClickListener(v -> {
|
binding.btnChangePhoto.setOnClickListener(v -> {
|
||||||
imagePickerHelper.showImagePickerDialog("Change Profile Photo", hasImage);
|
imagePickerHelper.showImagePickerDialog("Change Profile Photo", hasImage);
|
||||||
});
|
});
|
||||||
|
|
||||||
//Edit email button
|
//Edit email button
|
||||||
//When clicked open a dialog to change email
|
//When clicked open a dialog to change email
|
||||||
btnEditEmail.setOnClickListener(v -> {
|
binding.btnEditEmail.setOnClickListener(v -> {
|
||||||
//Make a text field for the user to enter the new email
|
//Make a text field for the user to enter the new email
|
||||||
EditText input = new EditText(requireContext());
|
EditText input = new EditText(requireContext());
|
||||||
input.setPadding(30,30,30,30);
|
input.setPadding(30,30,30,30);
|
||||||
input.setText(tvProfileEmail.getText().toString());
|
input.setText(binding.tvProfileEmail.getText().toString());
|
||||||
|
|
||||||
//set input type to email
|
//set input type to email
|
||||||
input.setInputType(android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
|
input.setInputType(android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
|
||||||
@@ -140,11 +122,11 @@ public class ProfileFragment extends Fragment {
|
|||||||
|
|
||||||
//Edit phone button
|
//Edit phone button
|
||||||
//When clicked open a dialog to change phone
|
//When clicked open a dialog to change phone
|
||||||
btnEditPhone.setOnClickListener(v -> {
|
binding.btnEditPhone.setOnClickListener(v -> {
|
||||||
//Make a text field for the user to enter the new email
|
//Make a text field for the user to enter the new email
|
||||||
EditText input = new EditText(requireContext());
|
EditText input = new EditText(requireContext());
|
||||||
input.setPadding(30,30,30,30);
|
input.setPadding(30,30,30,30);
|
||||||
input.setText(tvProfilePhone.getText().toString());
|
input.setText(binding.tvProfilePhone.getText().toString());
|
||||||
|
|
||||||
//set input type to phone number
|
//set input type to phone number
|
||||||
input.setInputType(android.view.inputmethod.EditorInfo.TYPE_CLASS_PHONE);
|
input.setInputType(android.view.inputmethod.EditorInfo.TYPE_CLASS_PHONE);
|
||||||
@@ -169,7 +151,7 @@ public class ProfileFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Logout button
|
//Logout button
|
||||||
btnLogout.setOnClickListener(v -> {
|
binding.btnLogout.setOnClickListener(v -> {
|
||||||
// Stop notification service before logging out so notifications stop
|
// Stop notification service before logging out so notifications stop
|
||||||
android.content.Intent serviceIntent = new android.content.Intent(requireContext(), ChatNotificationService.class);
|
android.content.Intent serviceIntent = new android.content.Intent(requireContext(), ChatNotificationService.class);
|
||||||
requireContext().stopService(serviceIntent);
|
requireContext().stopService(serviceIntent);
|
||||||
@@ -183,7 +165,13 @@ public class ProfileFragment extends Fragment {
|
|||||||
requireActivity().finish();
|
requireActivity().finish();
|
||||||
});
|
});
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -194,16 +182,16 @@ public class ProfileFragment extends Fragment {
|
|||||||
currentUser = result;
|
currentUser = result;
|
||||||
|
|
||||||
//set the user data to the view
|
//set the user data to the view
|
||||||
tvProfileName.setText(currentUser.getFullName());
|
binding.tvProfileName.setText(currentUser.getFullName());
|
||||||
tvProfileEmail.setText(currentUser.getEmail());
|
binding.tvProfileEmail.setText(currentUser.getEmail());
|
||||||
tvProfilePhone.setText(currentUser.getPhone());
|
binding.tvProfilePhone.setText(currentUser.getPhone());
|
||||||
tvProfileRole.setText(currentUser.getRole());
|
binding.tvProfileRole.setText(currentUser.getRole());
|
||||||
|
|
||||||
// get the avatar endpoint to load profile image and the token for authorization
|
// get the avatar endpoint to load profile image and the token for authorization
|
||||||
String avatarUrl = baseUrl + AuthApi.AVATAR_FILE_PATH;
|
String avatarUrl = baseUrl + AuthApi.AVATAR_FILE_PATH;
|
||||||
String token = tokenManager.getToken();
|
String token = tokenManager.getToken();
|
||||||
|
|
||||||
GlideUtils.loadImageWithToken(requireContext(), imgProfile, avatarUrl, token, R.drawable.placeholder, new GlideUtils.ImageLoadListener() {
|
GlideUtils.loadImageWithToken(requireContext(), binding.imgProfile, avatarUrl, token, R.drawable.placeholder, new GlideUtils.ImageLoadListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onResourceReady() {
|
public void onResourceReady() {
|
||||||
hasImage = true;
|
hasImage = true;
|
||||||
@@ -246,7 +234,7 @@ public class ProfileFragment extends Fragment {
|
|||||||
private void deleteAvatar() {
|
private void deleteAvatar() {
|
||||||
authApi.deleteAvatar().enqueue(RetrofitUtils.createCallback(requireContext(), "DELETE_AVATAR", "Avatar removed successfully", result -> {
|
authApi.deleteAvatar().enqueue(RetrofitUtils.createCallback(requireContext(), "DELETE_AVATAR", "Avatar removed successfully", result -> {
|
||||||
hasImage = false;
|
hasImage = false;
|
||||||
imgProfile.setImageResource(R.drawable.placeholder);
|
binding.imgProfile.setImageResource(R.drawable.placeholder);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,8 +248,8 @@ public class ProfileFragment extends Fragment {
|
|||||||
authApi.updateMe(updates).enqueue(RetrofitUtils.createCallback(requireContext(), "UPDATE_PROFILE", "Profile updated successfully", result -> {
|
authApi.updateMe(updates).enqueue(RetrofitUtils.createCallback(requireContext(), "UPDATE_PROFILE", "Profile updated successfully", result -> {
|
||||||
currentUser = result;
|
currentUser = result;
|
||||||
// Update the view with the new data from backend
|
// Update the view with the new data from backend
|
||||||
tvProfileEmail.setText(currentUser.getEmail());
|
binding.tvProfileEmail.setText(currentUser.getEmail());
|
||||||
tvProfilePhone.setText(currentUser.getPhone());
|
binding.tvProfilePhone.setText(currentUser.getPhone());
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.example.petstoremobile.fragments.listfragments;
|
|||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.*;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
import android.widget.*;
|
import android.widget.*;
|
||||||
@@ -12,20 +11,17 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.AdoptionAdapter;
|
import com.example.petstoremobile.adapters.AdoptionAdapter;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentAdoptionBinding;
|
||||||
import com.example.petstoremobile.dtos.AdoptionDTO;
|
import com.example.petstoremobile.dtos.AdoptionDTO;
|
||||||
import com.example.petstoremobile.fragments.ListFragment;
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
import com.example.petstoremobile.viewmodels.AdoptionViewModel;
|
import com.example.petstoremobile.viewmodels.AdoptionViewModel;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
|
||||||
import com.example.petstoremobile.utils.EventDecorator;
|
import com.example.petstoremobile.utils.EventDecorator;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|
||||||
import com.prolificinteractive.materialcalendarview.CalendarDay;
|
import com.prolificinteractive.materialcalendarview.CalendarDay;
|
||||||
import com.prolificinteractive.materialcalendarview.CalendarMode;
|
import com.prolificinteractive.materialcalendarview.CalendarMode;
|
||||||
import com.prolificinteractive.materialcalendarview.MaterialCalendarView;
|
import com.prolificinteractive.materialcalendarview.MaterialCalendarView;
|
||||||
import com.prolificinteractive.materialcalendarview.OnDateSelectedListener;
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -35,15 +31,11 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdoptionClickListener {
|
public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdoptionClickListener {
|
||||||
|
|
||||||
|
private FragmentAdoptionBinding binding;
|
||||||
private List<AdoptionDTO> adoptionList = new ArrayList<>();
|
private List<AdoptionDTO> adoptionList = new ArrayList<>();
|
||||||
private List<AdoptionDTO> filteredList = new ArrayList<>();
|
private List<AdoptionDTO> filteredList = new ArrayList<>();
|
||||||
private AdoptionAdapter adapter;
|
private AdoptionAdapter adapter;
|
||||||
private AdoptionViewModel viewModel;
|
private AdoptionViewModel viewModel;
|
||||||
private SwipeRefreshLayout swipeRefresh;
|
|
||||||
private EditText etSearch;
|
|
||||||
private ImageButton hamburger;
|
|
||||||
private ImageButton btnToggleCalendarMode;
|
|
||||||
private MaterialCalendarView calendarView;
|
|
||||||
private CalendarDay selectedCalendarDay;
|
private CalendarDay selectedCalendarDay;
|
||||||
private boolean isMonthMode = false;
|
private boolean isMonthMode = false;
|
||||||
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
|
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
|
||||||
@@ -63,22 +55,17 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_adoption, container, false);
|
binding = FragmentAdoptionBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
hamburger = view.findViewById(R.id.btnHamburgerAdoption);
|
setupRecyclerView();
|
||||||
calendarView = view.findViewById(R.id.calendarViewAdoption);
|
setupSearch();
|
||||||
btnToggleCalendarMode = view.findViewById(R.id.btnToggleCalendarModeAdoption);
|
setupSwipeRefresh();
|
||||||
|
|
||||||
setupRecyclerView(view);
|
|
||||||
setupSearch(view);
|
|
||||||
setupSwipeRefresh(view);
|
|
||||||
setupCalendar();
|
setupCalendar();
|
||||||
loadAdoptions();
|
loadAdoptions();
|
||||||
|
|
||||||
FloatingActionButton fab = view.findViewById(R.id.fabAddAdoption);
|
binding.fabAddAdoption.setOnClickListener(v -> openDetail(-1));
|
||||||
fab.setOnClickListener(v -> openDetail(-1));
|
|
||||||
|
|
||||||
hamburger.setOnClickListener(v -> {
|
binding.btnHamburgerAdoption.setOnClickListener(v -> {
|
||||||
Fragment parent = getParentFragment();
|
Fragment parent = getParentFragment();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
Fragment grandParent = parent.getParentFragment();
|
Fragment grandParent = parent.getParentFragment();
|
||||||
@@ -88,9 +75,15 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
btnToggleCalendarMode.setOnClickListener(v -> toggleCalendarMode());
|
binding.btnToggleCalendarModeAdoption.setOnClickListener(v -> toggleCalendarMode());
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,7 +91,7 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
*/
|
*/
|
||||||
private void toggleCalendarMode() {
|
private void toggleCalendarMode() {
|
||||||
isMonthMode = !isMonthMode;
|
isMonthMode = !isMonthMode;
|
||||||
calendarView.state().edit()
|
binding.calendarViewAdoption.state().edit()
|
||||||
.setCalendarDisplayMode(isMonthMode ? CalendarMode.MONTHS : CalendarMode.WEEKS)
|
.setCalendarDisplayMode(isMonthMode ? CalendarMode.MONTHS : CalendarMode.WEEKS)
|
||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
@@ -107,21 +100,18 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
* Sets up the date selection listener for the calendar.
|
* Sets up the date selection listener for the calendar.
|
||||||
*/
|
*/
|
||||||
private void setupCalendar() {
|
private void setupCalendar() {
|
||||||
calendarView.setOnDateChangedListener(new OnDateSelectedListener() {
|
binding.calendarViewAdoption.setOnDateChangedListener((widget, date, selected) -> {
|
||||||
@Override
|
if (selected) {
|
||||||
public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) {
|
if (date.equals(selectedCalendarDay)) {
|
||||||
if (selected) {
|
|
||||||
if (date.equals(selectedCalendarDay)) {
|
|
||||||
selectedCalendarDay = null;
|
|
||||||
calendarView.clearSelection();
|
|
||||||
} else {
|
|
||||||
selectedCalendarDay = date;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
selectedCalendarDay = null;
|
selectedCalendarDay = null;
|
||||||
|
binding.calendarViewAdoption.clearSelection();
|
||||||
|
} else {
|
||||||
|
selectedCalendarDay = date;
|
||||||
}
|
}
|
||||||
filter(etSearch.getText().toString());
|
} else {
|
||||||
|
selectedCalendarDay = null;
|
||||||
}
|
}
|
||||||
|
filter(binding.etSearchAdoption.getText().toString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,28 +134,26 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
Log.e("AdoptionFragment", "Error parsing date: " + adoption.getAdoptionDate());
|
Log.e("AdoptionFragment", "Error parsing date: " + adoption.getAdoptionDate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
calendarView.removeDecorators();
|
binding.calendarViewAdoption.removeDecorators();
|
||||||
calendarView.addDecorator(new EventDecorator(Color.RED, datesWithAdoptions));
|
binding.calendarViewAdoption.addDecorator(new EventDecorator(Color.RED, datesWithAdoptions));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the RecyclerView for displaying adoptions.
|
* Initializes the RecyclerView for displaying adoptions.
|
||||||
*/
|
*/
|
||||||
private void setupRecyclerView(View view) {
|
private void setupRecyclerView() {
|
||||||
RecyclerView rv = view.findViewById(R.id.recyclerViewAdoptions);
|
|
||||||
adapter = new AdoptionAdapter(filteredList, this);
|
adapter = new AdoptionAdapter(filteredList, this);
|
||||||
rv.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewAdoptions.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
rv.setAdapter(adapter);
|
binding.recyclerViewAdoptions.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the search bar for filtering
|
* Sets up the search bar for filtering
|
||||||
*/
|
*/
|
||||||
private void setupSearch(View view) {
|
private void setupSearch() {
|
||||||
etSearch = view.findViewById(R.id.etSearchAdoption);
|
binding.etSearchAdoption.addTextChangedListener(new android.text.TextWatcher() {
|
||||||
etSearch.addTextChangedListener(new TextWatcher() {
|
|
||||||
public void beforeTextChanged(CharSequence s, int a, int b, int c) {}
|
public void beforeTextChanged(CharSequence s, int a, int b, int c) {}
|
||||||
public void afterTextChanged(Editable s) {}
|
public void afterTextChanged(android.text.Editable s) {}
|
||||||
public void onTextChanged(CharSequence s, int a, int b, int c) {
|
public void onTextChanged(CharSequence s, int a, int b, int c) {
|
||||||
filter(s.toString());
|
filter(s.toString());
|
||||||
}
|
}
|
||||||
@@ -175,9 +163,8 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
/**
|
/**
|
||||||
* Sets up the SwipeRefreshLayout to reload adoption data.
|
* Sets up the SwipeRefreshLayout to reload adoption data.
|
||||||
*/
|
*/
|
||||||
private void setupSwipeRefresh(View view) {
|
private void setupSwipeRefresh() {
|
||||||
swipeRefresh = view.findViewById(R.id.swipeRefreshAdoption);
|
binding.swipeRefreshAdoption.setOnRefreshListener(this::loadAdoptions);
|
||||||
swipeRefresh.setOnRefreshListener(this::loadAdoptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -221,21 +208,21 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
switch (resource.status) {
|
switch (resource.status) {
|
||||||
case LOADING:
|
case LOADING:
|
||||||
// Show loading indicator
|
// Show loading indicator
|
||||||
if (swipeRefresh != null) swipeRefresh.setRefreshing(true);
|
binding.swipeRefreshAdoption.setRefreshing(true);
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
// Hide loading indicator and display data
|
// Hide loading indicator and display data
|
||||||
if (swipeRefresh != null) swipeRefresh.setRefreshing(false);
|
binding.swipeRefreshAdoption.setRefreshing(false);
|
||||||
if (resource.data != null) {
|
if (resource.data != null) {
|
||||||
adoptionList.clear();
|
adoptionList.clear();
|
||||||
adoptionList.addAll(resource.data.getContent());
|
adoptionList.addAll(resource.data.getContent());
|
||||||
updateCalendarDecorators();
|
updateCalendarDecorators();
|
||||||
filter(etSearch != null ? etSearch.getText().toString() : "");
|
filter(binding.etSearchAdoption != null ? binding.etSearchAdoption.getText().toString() : "");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
// Hide loading indicator and toast error message
|
// Hide loading indicator and toast error message
|
||||||
if (swipeRefresh != null) swipeRefresh.setRefreshing(false);
|
binding.swipeRefreshAdoption.setRefreshing(false);
|
||||||
Toast.makeText(getContext(), "Failed to load adoptions: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Failed to load adoptions: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
Log.e("AdoptionFragment", "Error loading adoptions: " + resource.message);
|
Log.e("AdoptionFragment", "Error loading adoptions: " + resource.message);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -9,20 +9,18 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.AppointmentAdapter;
|
import com.example.petstoremobile.adapters.AppointmentAdapter;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentAppointmentBinding;
|
||||||
import com.example.petstoremobile.dtos.AppointmentDTO;
|
import com.example.petstoremobile.dtos.AppointmentDTO;
|
||||||
import com.example.petstoremobile.dtos.ServiceDTO;
|
import com.example.petstoremobile.dtos.ServiceDTO;
|
||||||
import com.example.petstoremobile.dtos.PetDTO;
|
import com.example.petstoremobile.dtos.PetDTO;
|
||||||
@@ -32,11 +30,8 @@ import com.example.petstoremobile.viewmodels.PetViewModel;
|
|||||||
import com.example.petstoremobile.viewmodels.ServiceViewModel;
|
import com.example.petstoremobile.viewmodels.ServiceViewModel;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
import com.example.petstoremobile.utils.EventDecorator;
|
import com.example.petstoremobile.utils.EventDecorator;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|
||||||
import com.prolificinteractive.materialcalendarview.CalendarDay;
|
import com.prolificinteractive.materialcalendarview.CalendarDay;
|
||||||
import com.prolificinteractive.materialcalendarview.CalendarMode;
|
import com.prolificinteractive.materialcalendarview.CalendarMode;
|
||||||
import com.prolificinteractive.materialcalendarview.MaterialCalendarView;
|
|
||||||
import com.prolificinteractive.materialcalendarview.OnDateSelectedListener;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@@ -52,6 +47,7 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class AppointmentFragment extends Fragment implements AppointmentAdapter.OnAppointmentClickListener {
|
public class AppointmentFragment extends Fragment implements AppointmentAdapter.OnAppointmentClickListener {
|
||||||
|
|
||||||
|
private FragmentAppointmentBinding binding;
|
||||||
private List<AppointmentDTO> appointmentList = new ArrayList<>();
|
private List<AppointmentDTO> appointmentList = new ArrayList<>();
|
||||||
private List<AppointmentDTO> filteredList = new ArrayList<>();
|
private List<AppointmentDTO> filteredList = new ArrayList<>();
|
||||||
private List<PetDTO> petList = new ArrayList<>();
|
private List<PetDTO> petList = new ArrayList<>();
|
||||||
@@ -62,11 +58,6 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
|
|||||||
private PetViewModel petViewModel;
|
private PetViewModel petViewModel;
|
||||||
private ServiceViewModel serviceViewModel;
|
private ServiceViewModel serviceViewModel;
|
||||||
|
|
||||||
private SwipeRefreshLayout swipeRefreshLayout;
|
|
||||||
private EditText etSearch;
|
|
||||||
private ImageButton hamburger;
|
|
||||||
private ImageButton btnToggleCalendarMode;
|
|
||||||
private MaterialCalendarView calendarView;
|
|
||||||
private CalendarDay selectedCalendarDay;
|
private CalendarDay selectedCalendarDay;
|
||||||
private boolean isMonthMode = false;
|
private boolean isMonthMode = false;
|
||||||
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
|
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
|
||||||
@@ -88,24 +79,19 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_appointment, container, false);
|
binding = FragmentAppointmentBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
hamburger = view.findViewById(R.id.btnHamburger);
|
setupRecyclerView();
|
||||||
calendarView = view.findViewById(R.id.calendarView);
|
setupSearch();
|
||||||
btnToggleCalendarMode = view.findViewById(R.id.btnToggleCalendarMode);
|
setupSwipeRefresh();
|
||||||
|
|
||||||
setupRecyclerView(view);
|
|
||||||
setupSearch(view);
|
|
||||||
setupSwipeRefresh(view);
|
|
||||||
setupCalendar();
|
setupCalendar();
|
||||||
loadAppointmentData();
|
loadAppointmentData();
|
||||||
loadPets();
|
loadPets();
|
||||||
loadServices();
|
loadServices();
|
||||||
|
|
||||||
FloatingActionButton fabAdd = view.findViewById(R.id.fabAddAppointment);
|
binding.fabAddAppointment.setOnClickListener(v -> openAppointmentDetails(-1));
|
||||||
fabAdd.setOnClickListener(v -> openAppointmentDetails(-1));
|
|
||||||
|
|
||||||
hamburger.setOnClickListener(v -> {
|
binding.btnHamburger.setOnClickListener(v -> {
|
||||||
Fragment parent = getParentFragment();
|
Fragment parent = getParentFragment();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
Fragment grandParent = parent.getParentFragment();
|
Fragment grandParent = parent.getParentFragment();
|
||||||
@@ -115,9 +101,15 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
btnToggleCalendarMode.setOnClickListener(v -> toggleCalendarMode());
|
binding.btnToggleCalendarMode.setOnClickListener(v -> toggleCalendarMode());
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,7 +117,7 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
|
|||||||
*/
|
*/
|
||||||
private void toggleCalendarMode() {
|
private void toggleCalendarMode() {
|
||||||
isMonthMode = !isMonthMode;
|
isMonthMode = !isMonthMode;
|
||||||
calendarView.state().edit()
|
binding.calendarView.state().edit()
|
||||||
.setCalendarDisplayMode(isMonthMode ? CalendarMode.MONTHS : CalendarMode.WEEKS)
|
.setCalendarDisplayMode(isMonthMode ? CalendarMode.MONTHS : CalendarMode.WEEKS)
|
||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
@@ -134,21 +126,18 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
|
|||||||
* Sets up the date selection listener for the calendar.
|
* Sets up the date selection listener for the calendar.
|
||||||
*/
|
*/
|
||||||
private void setupCalendar() {
|
private void setupCalendar() {
|
||||||
calendarView.setOnDateChangedListener(new OnDateSelectedListener() {
|
binding.calendarView.setOnDateChangedListener((widget, date, selected) -> {
|
||||||
@Override
|
if (selected) {
|
||||||
public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) {
|
if (date.equals(selectedCalendarDay)) {
|
||||||
if (selected) {
|
|
||||||
if (date.equals(selectedCalendarDay)) {
|
|
||||||
selectedCalendarDay = null;
|
|
||||||
calendarView.clearSelection();
|
|
||||||
} else {
|
|
||||||
selectedCalendarDay = date;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
selectedCalendarDay = null;
|
selectedCalendarDay = null;
|
||||||
|
binding.calendarView.clearSelection();
|
||||||
|
} else {
|
||||||
|
selectedCalendarDay = date;
|
||||||
}
|
}
|
||||||
filterAppointments(etSearch.getText().toString());
|
} else {
|
||||||
|
selectedCalendarDay = null;
|
||||||
}
|
}
|
||||||
|
filterAppointments(binding.etSearchAppointment.getText().toString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,16 +161,15 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//update the indicators to the calendar
|
//update the indicators to the calendar
|
||||||
calendarView.removeDecorators();
|
binding.calendarView.removeDecorators();
|
||||||
calendarView.addDecorator(new EventDecorator(Color.RED, datesWithAppointments));
|
binding.calendarView.addDecorator(new EventDecorator(Color.RED, datesWithAppointments));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the search bar for filtering.
|
* Configures the search bar for filtering.
|
||||||
*/
|
*/
|
||||||
private void setupSearch(View view) {
|
private void setupSearch() {
|
||||||
etSearch = view.findViewById(R.id.etSearchAppointment);
|
binding.etSearchAppointment.addTextChangedListener(new TextWatcher() {
|
||||||
etSearch.addTextChangedListener(new TextWatcher() {
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
}
|
}
|
||||||
@@ -229,9 +217,8 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
|
|||||||
/**
|
/**
|
||||||
* Initializes the SwipeRefreshLayout to allow manual data refreshing.
|
* Initializes the SwipeRefreshLayout to allow manual data refreshing.
|
||||||
*/
|
*/
|
||||||
private void setupSwipeRefresh(View view) {
|
private void setupSwipeRefresh() {
|
||||||
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshAppointment);
|
binding.swipeRefreshAppointment.setOnRefreshListener(this::loadAppointmentData);
|
||||||
swipeRefreshLayout.setOnRefreshListener(this::loadAppointmentData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -290,21 +277,21 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
|
|||||||
switch (resource.status) {
|
switch (resource.status) {
|
||||||
case LOADING:
|
case LOADING:
|
||||||
// Show loading indicator
|
// Show loading indicator
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(true);
|
binding.swipeRefreshAppointment.setRefreshing(true);
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
// Hide loading indicator and display data
|
// Hide loading indicator and display data
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshAppointment.setRefreshing(false);
|
||||||
if (resource.data != null) {
|
if (resource.data != null) {
|
||||||
appointmentList.clear();
|
appointmentList.clear();
|
||||||
appointmentList.addAll(resource.data.getContent());
|
appointmentList.addAll(resource.data.getContent());
|
||||||
updateCalendarDecorators();
|
updateCalendarDecorators();
|
||||||
filterAppointments(etSearch != null ? etSearch.getText().toString() : "");
|
filterAppointments(binding.etSearchAppointment != null ? binding.etSearchAppointment.getText().toString() : "");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
// Hide loading indicator and toast error message
|
// Hide loading indicator and toast error message
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshAppointment.setRefreshing(false);
|
||||||
Toast.makeText(getContext(), "Failed to load appointments: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Failed to load appointments: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
Log.e("AppointmentFragment", "Error loading appointments: " + resource.message);
|
Log.e("AppointmentFragment", "Error loading appointments: " + resource.message);
|
||||||
break;
|
break;
|
||||||
@@ -336,34 +323,12 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a pet's name based on its ID.
|
|
||||||
*/
|
|
||||||
private String getPetName(Long id) {
|
|
||||||
for (PetDTO p : petList) {
|
|
||||||
if (p.getPetId().equals(id)) return p.getPetName();
|
|
||||||
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a service's name based on its ID.
|
|
||||||
*/
|
|
||||||
private String getServiceName(Long id) {
|
|
||||||
for (ServiceDTO s : serviceList) {
|
|
||||||
if (s.getServiceId().equals(id))return s.getServiceName();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the RecyclerView for displaying appointments.
|
* Initializes the RecyclerView for displaying appointments.
|
||||||
*/
|
*/
|
||||||
private void setupRecyclerView(View view) {
|
private void setupRecyclerView() {
|
||||||
RecyclerView recyclerView = view.findViewById(R.id.recyclerViewAppointments);
|
|
||||||
adapter = new AppointmentAdapter(filteredList, this);
|
adapter = new AppointmentAdapter(filteredList, this);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewAppointments.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
recyclerView.setAdapter(adapter);
|
binding.recyclerViewAppointments.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,6 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -24,11 +19,11 @@ import androidx.lifecycle.ViewModelProvider;
|
|||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
|
import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
|
||||||
import com.example.petstoremobile.adapters.InventoryAdapter;
|
import com.example.petstoremobile.adapters.InventoryAdapter;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentInventoryBinding;
|
||||||
import com.example.petstoremobile.dtos.CategoryDTO;
|
import com.example.petstoremobile.dtos.CategoryDTO;
|
||||||
import com.example.petstoremobile.dtos.InventoryDTO;
|
import com.example.petstoremobile.dtos.InventoryDTO;
|
||||||
import com.example.petstoremobile.fragments.ListFragment;
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
@@ -46,18 +41,12 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
|
|||||||
private static final String TAG = "InventoryFragment";
|
private static final String TAG = "InventoryFragment";
|
||||||
private static final int PAGE_SIZE = 20;
|
private static final int PAGE_SIZE = 20;
|
||||||
|
|
||||||
|
private FragmentInventoryBinding binding;
|
||||||
private final List<InventoryDTO> inventoryList = new ArrayList<>();
|
private final List<InventoryDTO> inventoryList = new ArrayList<>();
|
||||||
private final List<CategoryDTO> categoryList = new ArrayList<>();
|
private final List<CategoryDTO> categoryList = new ArrayList<>();
|
||||||
private InventoryAdapter adapter;
|
private InventoryAdapter adapter;
|
||||||
private InventoryViewModel viewModel;
|
private InventoryViewModel viewModel;
|
||||||
|
|
||||||
private SwipeRefreshLayout swipeRefreshLayout;
|
|
||||||
private EditText etSearch;
|
|
||||||
private Spinner spinnerCategory;
|
|
||||||
private ImageButton hamburger;
|
|
||||||
private Button btnBulkDelete;
|
|
||||||
private TextView tvSelectionCount;
|
|
||||||
|
|
||||||
// Debounce search
|
// Debounce search
|
||||||
private final Handler searchHandler = new Handler(Looper.getMainLooper());
|
private final Handler searchHandler = new Handler(Looper.getMainLooper());
|
||||||
private Runnable searchRunnable;
|
private Runnable searchRunnable;
|
||||||
@@ -89,23 +78,17 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_inventory, container, false);
|
binding = FragmentInventoryBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
hamburger = view.findViewById(R.id.btnHamburger);
|
setupRecyclerView();
|
||||||
btnBulkDelete = view.findViewById(R.id.btnBulkDelete);
|
setupSearch();
|
||||||
tvSelectionCount = view.findViewById(R.id.tvSelectionCount);
|
setupSwipeRefresh();
|
||||||
spinnerCategory = view.findViewById(R.id.spinnerCategory);
|
|
||||||
|
|
||||||
setupRecyclerView(view);
|
|
||||||
setupSearch(view);
|
|
||||||
setupSwipeRefresh(view);
|
|
||||||
loadCategories(); // loads categories then triggers loadInventory
|
loadCategories(); // loads categories then triggers loadInventory
|
||||||
loadInventory(true);
|
loadInventory(true);
|
||||||
|
|
||||||
view.findViewById(R.id.fabAddInventory)
|
binding.fabAddInventory.setOnClickListener(v -> openDetail(null));
|
||||||
.setOnClickListener(v -> openDetail(null));
|
|
||||||
|
|
||||||
hamburger.setOnClickListener(v -> {
|
binding.btnHamburger.setOnClickListener(v -> {
|
||||||
Fragment parent = getParentFragment();
|
Fragment parent = getParentFragment();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
Fragment grandParent = parent.getParentFragment();
|
Fragment grandParent = parent.getParentFragment();
|
||||||
@@ -115,9 +98,15 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
btnBulkDelete.setOnClickListener(v -> confirmBulkDelete());
|
binding.btnBulkDelete.setOnClickListener(v -> confirmBulkDelete());
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -153,9 +142,9 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
|
|||||||
android.R.layout.simple_spinner_item,
|
android.R.layout.simple_spinner_item,
|
||||||
categoryNames);
|
categoryNames);
|
||||||
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
spinnerCategory.setAdapter(spinnerAdapter);
|
binding.spinnerCategory.setAdapter(spinnerAdapter);
|
||||||
|
|
||||||
spinnerCategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
binding.spinnerCategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
if (!spinnerReady) {
|
if (!spinnerReady) {
|
||||||
@@ -181,15 +170,12 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
|
|||||||
/**
|
/**
|
||||||
* Sets up the search bar for filtering.
|
* Sets up the search bar for filtering.
|
||||||
*/
|
*/
|
||||||
private void setupSearch(View view) {
|
private void setupSearch() {
|
||||||
etSearch = view.findViewById(R.id.etSearchInventory);
|
binding.etSearchInventory.addTextChangedListener(new TextWatcher() {
|
||||||
etSearch.addTextChangedListener(new TextWatcher() {
|
@Override public void beforeTextChanged(CharSequence s, int i, int i1, int i2) {
|
||||||
@Override
|
|
||||||
public void beforeTextChanged(CharSequence s, int i, int i1, int i2) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public void afterTextChanged(Editable s) {
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -208,18 +194,17 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
|
|||||||
/**
|
/**
|
||||||
* Initializes the RecyclerView with a layout manager, and adapter.
|
* Initializes the RecyclerView with a layout manager, and adapter.
|
||||||
*/
|
*/
|
||||||
private void setupRecyclerView(View view) {
|
private void setupRecyclerView() {
|
||||||
RecyclerView rv = view.findViewById(R.id.recyclerViewInventory);
|
|
||||||
adapter = new InventoryAdapter(inventoryList, this);
|
adapter = new InventoryAdapter(inventoryList, this);
|
||||||
rv.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewInventory.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
rv.setAdapter(adapter);
|
binding.recyclerViewInventory.setAdapter(adapter);
|
||||||
|
|
||||||
rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
binding.recyclerViewInventory.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||||
if (dy <= 0)
|
if (dy <= 0)
|
||||||
return;
|
return;
|
||||||
LinearLayoutManager lm = (LinearLayoutManager) rv.getLayoutManager();
|
LinearLayoutManager lm = (LinearLayoutManager) binding.recyclerViewInventory.getLayoutManager();
|
||||||
if (lm == null)
|
if (lm == null)
|
||||||
return;
|
return;
|
||||||
int visible = lm.getChildCount();
|
int visible = lm.getChildCount();
|
||||||
@@ -235,9 +220,8 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
|
|||||||
/**
|
/**
|
||||||
* Sets up the SwipeRefreshLayout to reload the first page of inventory items.
|
* Sets up the SwipeRefreshLayout to reload the first page of inventory items.
|
||||||
*/
|
*/
|
||||||
private void setupSwipeRefresh(View view) {
|
private void setupSwipeRefresh() {
|
||||||
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshInventory);
|
binding.swipeRefreshInventory.setOnRefreshListener(() -> loadInventory(true));
|
||||||
swipeRefreshLayout.setOnRefreshListener(() -> loadInventory(true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -264,12 +248,12 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
|
|||||||
case LOADING:
|
case LOADING:
|
||||||
// Show loading indicator
|
// Show loading indicator
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(true);
|
binding.swipeRefreshInventory.setRefreshing(true);
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
// Hide loading indicator and display data
|
// Hide loading indicator and display data
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshInventory.setRefreshing(false);
|
||||||
if (resource.data != null) {
|
if (resource.data != null) {
|
||||||
if (reset) inventoryList.clear();
|
if (reset) inventoryList.clear();
|
||||||
inventoryList.addAll(resource.data.getContent());
|
inventoryList.addAll(resource.data.getContent());
|
||||||
@@ -281,7 +265,7 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
|
|||||||
case ERROR:
|
case ERROR:
|
||||||
// Hide loading indicator and toast error message
|
// Hide loading indicator and toast error message
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshInventory.setRefreshing(false);
|
||||||
Log.e(TAG, "Error: " + resource.message);
|
Log.e(TAG, "Error: " + resource.message);
|
||||||
Toast.makeText(getContext(), "Failed to load inventory: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Failed to load inventory: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
break;
|
break;
|
||||||
@@ -343,10 +327,10 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
|
|||||||
* Hides the bulk deletion UI bar.
|
* Hides the bulk deletion UI bar.
|
||||||
*/
|
*/
|
||||||
private void hideBulkDeleteBar() {
|
private void hideBulkDeleteBar() {
|
||||||
if (btnBulkDelete != null)
|
if (binding != null) {
|
||||||
btnBulkDelete.setVisibility(View.GONE);
|
binding.btnBulkDelete.setVisibility(View.GONE);
|
||||||
if (tvSelectionCount != null)
|
binding.tvSelectionCount.setVisibility(View.GONE);
|
||||||
tvSelectionCount.setVisibility(View.GONE);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -389,9 +373,9 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
|
|||||||
@Override
|
@Override
|
||||||
public void onSelectionChanged(int selectedCount) {
|
public void onSelectionChanged(int selectedCount) {
|
||||||
if (selectedCount > 0) {
|
if (selectedCount > 0) {
|
||||||
btnBulkDelete.setVisibility(View.VISIBLE);
|
binding.btnBulkDelete.setVisibility(View.VISIBLE);
|
||||||
tvSelectionCount.setVisibility(View.VISIBLE);
|
binding.tvSelectionCount.setVisibility(View.VISIBLE);
|
||||||
tvSelectionCount.setText(selectedCount + " selected");
|
binding.tvSelectionCount.setText(selectedCount + " selected");
|
||||||
} else {
|
} else {
|
||||||
hideBulkDeleteBar();
|
hideBulkDeleteBar();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,12 @@ package com.example.petstoremobile.fragments.listfragments;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
|
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
@@ -17,18 +16,15 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
|
import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
|
||||||
import com.example.petstoremobile.adapters.PetAdapter;
|
import com.example.petstoremobile.adapters.PetAdapter;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentPetBinding;
|
||||||
import com.example.petstoremobile.dtos.PetDTO;
|
import com.example.petstoremobile.dtos.PetDTO;
|
||||||
import com.example.petstoremobile.fragments.ListFragment;
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
import com.example.petstoremobile.viewmodels.PetViewModel;
|
import com.example.petstoremobile.viewmodels.PetViewModel;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -40,16 +36,13 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class PetFragment extends Fragment implements PetAdapter.OnPetClickListener {
|
public class PetFragment extends Fragment implements PetAdapter.OnPetClickListener {
|
||||||
|
private FragmentPetBinding binding;
|
||||||
private List<PetDTO> petList = new ArrayList<>();
|
private List<PetDTO> petList = new ArrayList<>();
|
||||||
private List<PetDTO> filteredList = new ArrayList<>();
|
private List<PetDTO> filteredList = new ArrayList<>();
|
||||||
private ImageButton hamburger;
|
|
||||||
private PetAdapter adapter;
|
private PetAdapter adapter;
|
||||||
private PetViewModel viewModel;
|
private PetViewModel viewModel;
|
||||||
|
|
||||||
@Inject @Named("baseUrl") String baseUrl;
|
@Inject @Named("baseUrl") String baseUrl;
|
||||||
private SwipeRefreshLayout swipeRefreshLayout;
|
|
||||||
private EditText etSearch;
|
|
||||||
private Spinner spinnerStatus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the fragment and its associated PetViewModel.
|
* Initializes the fragment and its associated PetViewModel.
|
||||||
@@ -64,21 +57,18 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
* Sets up the fragment's UI components, including RecyclerView, search, status filter, and swipe-to-refresh.
|
* Sets up the fragment's UI components, including RecyclerView, search, status filter, and swipe-to-refresh.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_pet, container, false);
|
binding = FragmentPetBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
hamburger = view.findViewById(R.id.btnHamburger);
|
setupRecyclerView();
|
||||||
|
setupSearch();
|
||||||
|
setupStatusFilter();
|
||||||
|
setupSwipeRefresh();
|
||||||
|
|
||||||
setupRecyclerView(view);
|
binding.fabAddPet.setOnClickListener(v -> openPetDetails());
|
||||||
setupSearch(view);
|
|
||||||
setupStatusFilter(view);
|
|
||||||
setupSwipeRefresh(view);
|
|
||||||
|
|
||||||
FloatingActionButton fabAddPet = view.findViewById(R.id.fabAddPet);
|
binding.btnHamburger.setOnClickListener(v -> {
|
||||||
fabAddPet.setOnClickListener(v -> openPetDetails());
|
|
||||||
|
|
||||||
hamburger.setOnClickListener(v -> {
|
|
||||||
Fragment parent = getParentFragment();
|
Fragment parent = getParentFragment();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
Fragment grandParent = parent.getParentFragment();
|
Fragment grandParent = parent.getParentFragment();
|
||||||
@@ -88,7 +78,13 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,9 +99,8 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
/**
|
/**
|
||||||
* Configures the search bar with a for filtering.
|
* Configures the search bar with a for filtering.
|
||||||
*/
|
*/
|
||||||
private void setupSearch(View view) {
|
private void setupSearch() {
|
||||||
etSearch = view.findViewById(R.id.etSearchPet);
|
binding.etSearchPet.addTextChangedListener(new TextWatcher() {
|
||||||
etSearch.addTextChangedListener(new TextWatcher() {
|
|
||||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
filterPets();
|
filterPets();
|
||||||
@@ -117,14 +112,13 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
/**
|
/**
|
||||||
* Configures the status filter spinner.
|
* Configures the status filter spinner.
|
||||||
*/
|
*/
|
||||||
private void setupStatusFilter(View view) {
|
private void setupStatusFilter() {
|
||||||
spinnerStatus = view.findViewById(R.id.spinnerStatus);
|
|
||||||
String[] statuses = {"All Statuses", "Available", "Adopted"};
|
String[] statuses = {"All Statuses", "Available", "Adopted"};
|
||||||
BlackTextArrayAdapter<String> adapter = new BlackTextArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, statuses);
|
BlackTextArrayAdapter<String> adapter = new BlackTextArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, statuses);
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
spinnerStatus.setAdapter(adapter);
|
binding.spinnerStatus.setAdapter(adapter);
|
||||||
|
|
||||||
spinnerStatus.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
binding.spinnerStatus.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
filterPets();
|
filterPets();
|
||||||
@@ -139,8 +133,8 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
* Filters the pet list based on both the search query and the selected status.
|
* Filters the pet list based on both the search query and the selected status.
|
||||||
*/
|
*/
|
||||||
private void filterPets() {
|
private void filterPets() {
|
||||||
String query = etSearch.getText().toString().toLowerCase();
|
String query = binding.etSearchPet.getText().toString().toLowerCase();
|
||||||
String selectedStatus = spinnerStatus.getSelectedItem().toString();
|
String selectedStatus = binding.spinnerStatus.getSelectedItem().toString();
|
||||||
|
|
||||||
filteredList.clear();
|
filteredList.clear();
|
||||||
for (PetDTO p : petList) {
|
for (PetDTO p : petList) {
|
||||||
@@ -162,9 +156,8 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
/**
|
/**
|
||||||
* Sets up the SwipeRefreshLayout to allow manual re-fetching of pet data.
|
* Sets up the SwipeRefreshLayout to allow manual re-fetching of pet data.
|
||||||
*/
|
*/
|
||||||
private void setupSwipeRefresh(View view) {
|
private void setupSwipeRefresh() {
|
||||||
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshPet);
|
binding.swipeRefreshPet.setOnRefreshListener(this::loadPetData);
|
||||||
swipeRefreshLayout.setOnRefreshListener(this::loadPetData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -208,19 +201,15 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
* Fetches all pet data from the server via the ViewModel and updates the UI.
|
* Fetches all pet data from the server via the ViewModel and updates the UI.
|
||||||
*/
|
*/
|
||||||
private void loadPetData() {
|
private void loadPetData() {
|
||||||
//Load all pets from the backend using viewModel
|
|
||||||
viewModel.getAllPets(0, 100).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.getAllPets(0, 100).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
|
||||||
// Check the status to see if the resource is loaded and display the data
|
|
||||||
switch (resource.status) {
|
switch (resource.status) {
|
||||||
case LOADING:
|
case LOADING:
|
||||||
// Show loading indicator
|
binding.swipeRefreshPet.setRefreshing(true);
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(true);
|
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
// Hide loading indicator and display data
|
binding.swipeRefreshPet.setRefreshing(false);
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);
|
|
||||||
if (resource.data != null) {
|
if (resource.data != null) {
|
||||||
petList.clear();
|
petList.clear();
|
||||||
petList.addAll(resource.data.getContent());
|
petList.addAll(resource.data.getContent());
|
||||||
@@ -228,8 +217,7 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
// Hide loading indicator and toast error message
|
binding.swipeRefreshPet.setRefreshing(false);
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);
|
|
||||||
Toast.makeText(getContext(), "Failed to load pets: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Failed to load pets: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
Log.e("PetFragment", "Error loading pets: " + resource.message);
|
Log.e("PetFragment", "Error loading pets: " + resource.message);
|
||||||
break;
|
break;
|
||||||
@@ -240,11 +228,10 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
/**
|
/**
|
||||||
* Initializes the RecyclerView with a layout manager and adapter for displaying pets.
|
* Initializes the RecyclerView with a layout manager and adapter for displaying pets.
|
||||||
*/
|
*/
|
||||||
private void setupRecyclerView(View view) {
|
private void setupRecyclerView() {
|
||||||
RecyclerView recyclerView = view.findViewById(R.id.recyclerViewPets);
|
|
||||||
adapter = new PetAdapter(filteredList, this);
|
adapter = new PetAdapter(filteredList, this);
|
||||||
adapter.setBaseUrl(baseUrl);
|
adapter.setBaseUrl(baseUrl);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewPets.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
recyclerView.setAdapter(adapter);
|
binding.recyclerViewPets.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,16 +11,15 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.ProductAdapter;
|
import com.example.petstoremobile.adapters.ProductAdapter;
|
||||||
import com.example.petstoremobile.api.auth.TokenManager;
|
import com.example.petstoremobile.api.auth.TokenManager;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentProductBinding;
|
||||||
import com.example.petstoremobile.dtos.ProductDTO;
|
import com.example.petstoremobile.dtos.ProductDTO;
|
||||||
import com.example.petstoremobile.fragments.ListFragment;
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
import com.example.petstoremobile.viewmodels.ProductViewModel;
|
import com.example.petstoremobile.viewmodels.ProductViewModel;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -31,11 +30,10 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class ProductFragment extends Fragment implements ProductAdapter.OnProductClickListener {
|
public class ProductFragment extends Fragment implements ProductAdapter.OnProductClickListener {
|
||||||
|
|
||||||
|
private FragmentProductBinding binding;
|
||||||
private List<ProductDTO> productList = new ArrayList<>();
|
private List<ProductDTO> productList = new ArrayList<>();
|
||||||
private List<ProductDTO> filteredList = new ArrayList<>();
|
private List<ProductDTO> filteredList = new ArrayList<>();
|
||||||
private ProductAdapter adapter;
|
private ProductAdapter adapter;
|
||||||
private SwipeRefreshLayout swipeRefresh;
|
|
||||||
private EditText etSearch;
|
|
||||||
private ProductViewModel viewModel;
|
private ProductViewModel viewModel;
|
||||||
|
|
||||||
@Inject @Named("baseUrl") String baseUrl;
|
@Inject @Named("baseUrl") String baseUrl;
|
||||||
@@ -56,19 +54,17 @@ public class ProductFragment extends Fragment implements ProductAdapter.OnProduc
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_product, container, false);
|
binding = FragmentProductBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
setupRecyclerView(view);
|
setupRecyclerView();
|
||||||
setupSearch(view);
|
setupSearch();
|
||||||
setupSwipeRefresh(view);
|
setupSwipeRefresh();
|
||||||
|
|
||||||
loadProducts();
|
loadProducts();
|
||||||
|
|
||||||
FloatingActionButton fab = view.findViewById(R.id.fabAddProduct);
|
binding.fabAddProduct.setOnClickListener(v -> openDetail(-1));
|
||||||
fab.setOnClickListener(v -> openDetail(-1));
|
|
||||||
|
|
||||||
ImageButton hamburger = view.findViewById(R.id.btnHamburgerProduct);
|
binding.btnHamburgerProduct.setOnClickListener(v -> {
|
||||||
hamburger.setOnClickListener(v -> {
|
|
||||||
Fragment parent = getParentFragment();
|
Fragment parent = getParentFragment();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
Fragment grandParent = parent.getParentFragment();
|
Fragment grandParent = parent.getParentFragment();
|
||||||
@@ -78,27 +74,31 @@ public class ProductFragment extends Fragment implements ProductAdapter.OnProduc
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the RecyclerView with a layout manager and adapter for displaying products.
|
* Initializes the RecyclerView with a layout manager and adapter for displaying products.
|
||||||
*/
|
*/
|
||||||
private void setupRecyclerView(View view) {
|
private void setupRecyclerView() {
|
||||||
RecyclerView rv = view.findViewById(R.id.recyclerViewProducts);
|
|
||||||
adapter = new ProductAdapter(filteredList, this);
|
adapter = new ProductAdapter(filteredList, this);
|
||||||
adapter.setBaseUrl(baseUrl);
|
adapter.setBaseUrl(baseUrl);
|
||||||
adapter.setToken(tokenManager.getToken());
|
adapter.setToken(tokenManager.getToken());
|
||||||
rv.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewProducts.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
rv.setAdapter(adapter);
|
binding.recyclerViewProducts.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the search bar for filtering.
|
* Configures the search bar for filtering.
|
||||||
*/
|
*/
|
||||||
private void setupSearch(View view) {
|
private void setupSearch() {
|
||||||
etSearch = view.findViewById(R.id.etSearchProduct);
|
binding.etSearchProduct.addTextChangedListener(new TextWatcher() {
|
||||||
etSearch.addTextChangedListener(new TextWatcher() {
|
|
||||||
public void beforeTextChanged(CharSequence s, int a, int b, int c) {}
|
public void beforeTextChanged(CharSequence s, int a, int b, int c) {}
|
||||||
public void afterTextChanged(Editable s) {}
|
public void afterTextChanged(Editable s) {}
|
||||||
public void onTextChanged(CharSequence s, int a, int b, int c) {
|
public void onTextChanged(CharSequence s, int a, int b, int c) {
|
||||||
@@ -110,16 +110,15 @@ public class ProductFragment extends Fragment implements ProductAdapter.OnProduc
|
|||||||
/**
|
/**
|
||||||
* Sets up the SwipeRefreshLayout to allow manual re-fetching of product data.
|
* Sets up the SwipeRefreshLayout to allow manual re-fetching of product data.
|
||||||
*/
|
*/
|
||||||
private void setupSwipeRefresh(View view) {
|
private void setupSwipeRefresh() {
|
||||||
swipeRefresh = view.findViewById(R.id.swipeRefreshProduct);
|
binding.swipeRefreshProduct.setOnRefreshListener(this::loadProducts);
|
||||||
swipeRefresh.setOnRefreshListener(this::loadProducts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters the product list based on the search query across name, category, and description.
|
* Filters the product list based on the search query across name, category, and description.
|
||||||
*/
|
*/
|
||||||
private void filter() {
|
private void filter() {
|
||||||
String query = etSearch.getText().toString().toLowerCase();
|
String query = binding.etSearchProduct.getText().toString().toLowerCase();
|
||||||
|
|
||||||
filteredList.clear();
|
filteredList.clear();
|
||||||
for (ProductDTO p : productList) {
|
for (ProductDTO p : productList) {
|
||||||
@@ -139,19 +138,15 @@ public class ProductFragment extends Fragment implements ProductAdapter.OnProduc
|
|||||||
* Fetches all product data from the server through the ViewModel and updates the UI.
|
* Fetches all product data from the server through the ViewModel and updates the UI.
|
||||||
*/
|
*/
|
||||||
private void loadProducts() {
|
private void loadProducts() {
|
||||||
//Load all products from the backend using viewModel
|
|
||||||
viewModel.getAllProducts(null, 0, 100).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.getAllProducts(null, 0, 100).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
|
||||||
// Check the status to see if the resource is loaded and display the data
|
|
||||||
switch (resource.status) {
|
switch (resource.status) {
|
||||||
case LOADING:
|
case LOADING:
|
||||||
// Show loading indicator
|
binding.swipeRefreshProduct.setRefreshing(true);
|
||||||
if (swipeRefresh != null) swipeRefresh.setRefreshing(true);
|
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
// Hide loading indicator and display data
|
binding.swipeRefreshProduct.setRefreshing(false);
|
||||||
if (swipeRefresh != null) swipeRefresh.setRefreshing(false);
|
|
||||||
if (resource.data != null) {
|
if (resource.data != null) {
|
||||||
productList.clear();
|
productList.clear();
|
||||||
productList.addAll(resource.data.getContent());
|
productList.addAll(resource.data.getContent());
|
||||||
@@ -159,8 +154,7 @@ public class ProductFragment extends Fragment implements ProductAdapter.OnProduc
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
// Hide loading indicator and toast error message
|
binding.swipeRefreshProduct.setRefreshing(false);
|
||||||
if (swipeRefresh != null) swipeRefresh.setRefreshing(false);
|
|
||||||
Toast.makeText(getContext(), "Failed to load products: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Failed to load products: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
Log.e("ProductFragment", "Error loading products: " + resource.message);
|
Log.e("ProductFragment", "Error loading products: " + resource.message);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -11,15 +11,14 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.ProductSupplierAdapter;
|
import com.example.petstoremobile.adapters.ProductSupplierAdapter;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentProductSupplierBinding;
|
||||||
import com.example.petstoremobile.dtos.ProductSupplierDTO;
|
import com.example.petstoremobile.dtos.ProductSupplierDTO;
|
||||||
import com.example.petstoremobile.fragments.ListFragment;
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
import com.example.petstoremobile.viewmodels.ProductSupplierViewModel;
|
import com.example.petstoremobile.viewmodels.ProductSupplierViewModel;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
@@ -28,11 +27,10 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
public class ProductSupplierFragment extends Fragment
|
public class ProductSupplierFragment extends Fragment
|
||||||
implements ProductSupplierAdapter.OnProductSupplierClickListener {
|
implements ProductSupplierAdapter.OnProductSupplierClickListener {
|
||||||
|
|
||||||
|
private FragmentProductSupplierBinding binding;
|
||||||
private List<ProductSupplierDTO> psList = new ArrayList<>();
|
private List<ProductSupplierDTO> psList = new ArrayList<>();
|
||||||
private List<ProductSupplierDTO> filteredList = new ArrayList<>();
|
private List<ProductSupplierDTO> filteredList = new ArrayList<>();
|
||||||
private ProductSupplierAdapter adapter;
|
private ProductSupplierAdapter adapter;
|
||||||
private SwipeRefreshLayout swipeRefresh;
|
|
||||||
private EditText etSearch;
|
|
||||||
private ProductSupplierViewModel viewModel;
|
private ProductSupplierViewModel viewModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,18 +48,16 @@ public class ProductSupplierFragment extends Fragment
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_product_supplier, container, false);
|
binding = FragmentProductSupplierBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
setupRecyclerView(view);
|
setupRecyclerView();
|
||||||
setupSearch(view);
|
setupSearch();
|
||||||
setupSwipeRefresh(view);
|
setupSwipeRefresh();
|
||||||
loadData();
|
loadData();
|
||||||
|
|
||||||
FloatingActionButton fab = view.findViewById(R.id.fabAddPS);
|
binding.fabAddPS.setOnClickListener(v -> openDetail(-1));
|
||||||
fab.setOnClickListener(v -> openDetail(-1));
|
|
||||||
|
|
||||||
ImageButton hamburger = view.findViewById(R.id.btnHamburgerPS);
|
binding.btnHamburgerPS.setOnClickListener(v -> {
|
||||||
hamburger.setOnClickListener(v -> {
|
|
||||||
Fragment parent = getParentFragment();
|
Fragment parent = getParentFragment();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
Fragment grandParent = parent.getParentFragment();
|
Fragment grandParent = parent.getParentFragment();
|
||||||
@@ -71,25 +67,29 @@ public class ProductSupplierFragment extends Fragment
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the RecyclerView with a layout manager and adapter for product-supplier data.
|
* Initializes the RecyclerView with a layout manager and adapter for product-supplier data.
|
||||||
*/
|
*/
|
||||||
private void setupRecyclerView(View view) {
|
private void setupRecyclerView() {
|
||||||
RecyclerView rv = view.findViewById(R.id.recyclerViewPS);
|
|
||||||
adapter = new ProductSupplierAdapter(filteredList, this);
|
adapter = new ProductSupplierAdapter(filteredList, this);
|
||||||
rv.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewPS.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
rv.setAdapter(adapter);
|
binding.recyclerViewPS.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the search bar for filtering.
|
* Configures the search bar for filtering.
|
||||||
*/
|
*/
|
||||||
private void setupSearch(View view) {
|
private void setupSearch() {
|
||||||
etSearch = view.findViewById(R.id.etSearchPS);
|
binding.etSearchPS.addTextChangedListener(new TextWatcher() {
|
||||||
etSearch.addTextChangedListener(new TextWatcher() {
|
|
||||||
public void beforeTextChanged(CharSequence s, int a, int b, int c) {}
|
public void beforeTextChanged(CharSequence s, int a, int b, int c) {}
|
||||||
public void afterTextChanged(Editable s) {}
|
public void afterTextChanged(Editable s) {}
|
||||||
public void onTextChanged(CharSequence s, int a, int b, int c) {
|
public void onTextChanged(CharSequence s, int a, int b, int c) {
|
||||||
@@ -101,9 +101,8 @@ public class ProductSupplierFragment extends Fragment
|
|||||||
/**
|
/**
|
||||||
* Sets up the SwipeRefreshLayout to allow manual reloading of product-supplier data.
|
* Sets up the SwipeRefreshLayout to allow manual reloading of product-supplier data.
|
||||||
*/
|
*/
|
||||||
private void setupSwipeRefresh(View view) {
|
private void setupSwipeRefresh() {
|
||||||
swipeRefresh = view.findViewById(R.id.swipeRefreshPS);
|
binding.swipeRefreshPS.setOnRefreshListener(this::loadData);
|
||||||
swipeRefresh.setOnRefreshListener(this::loadData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,20 +136,20 @@ public class ProductSupplierFragment extends Fragment
|
|||||||
switch (resource.status) {
|
switch (resource.status) {
|
||||||
case LOADING:
|
case LOADING:
|
||||||
// Show loading indicator
|
// Show loading indicator
|
||||||
if (swipeRefresh != null) swipeRefresh.setRefreshing(true);
|
binding.swipeRefreshPS.setRefreshing(true);
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
// Hide loading indicator and display data
|
// Hide loading indicator and display data
|
||||||
if (swipeRefresh != null) swipeRefresh.setRefreshing(false);
|
binding.swipeRefreshPS.setRefreshing(false);
|
||||||
if (resource.data != null) {
|
if (resource.data != null) {
|
||||||
psList.clear();
|
psList.clear();
|
||||||
psList.addAll(resource.data.getContent());
|
psList.addAll(resource.data.getContent());
|
||||||
filter(etSearch != null ? etSearch.getText().toString() : "");
|
filter(binding.etSearchPS != null ? binding.etSearchPS.getText().toString() : "");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
// Hide loading indicator and toast error message
|
// Hide loading indicator and toast error message
|
||||||
if (swipeRefresh != null) swipeRefresh.setRefreshing(false);
|
binding.swipeRefreshPS.setRefreshing(false);
|
||||||
Toast.makeText(getContext(), "Failed to load: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Failed to load: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
Log.e("PSFragment", "Error loading: " + resource.message);
|
Log.e("PSFragment", "Error loading: " + resource.message);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.PurchaseOrderAdapter;
|
import com.example.petstoremobile.adapters.PurchaseOrderAdapter;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentPurchaseOrderBinding;
|
||||||
import com.example.petstoremobile.dtos.PurchaseOrderDTO;
|
import com.example.petstoremobile.dtos.PurchaseOrderDTO;
|
||||||
import com.example.petstoremobile.fragments.ListFragment;
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
import com.example.petstoremobile.viewmodels.PurchaseOrderViewModel;
|
import com.example.petstoremobile.viewmodels.PurchaseOrderViewModel;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
@@ -27,11 +27,10 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
public class PurchaseOrderFragment extends Fragment
|
public class PurchaseOrderFragment extends Fragment
|
||||||
implements PurchaseOrderAdapter.OnPurchaseOrderClickListener {
|
implements PurchaseOrderAdapter.OnPurchaseOrderClickListener {
|
||||||
|
|
||||||
|
private FragmentPurchaseOrderBinding binding;
|
||||||
private List<PurchaseOrderDTO> poList = new ArrayList<>();
|
private List<PurchaseOrderDTO> poList = new ArrayList<>();
|
||||||
private List<PurchaseOrderDTO> filteredList = new ArrayList<>();
|
private List<PurchaseOrderDTO> filteredList = new ArrayList<>();
|
||||||
private PurchaseOrderAdapter adapter;
|
private PurchaseOrderAdapter adapter;
|
||||||
private SwipeRefreshLayout swipeRefresh;
|
|
||||||
private EditText etSearch;
|
|
||||||
private PurchaseOrderViewModel viewModel;
|
private PurchaseOrderViewModel viewModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,17 +46,16 @@ public class PurchaseOrderFragment extends Fragment
|
|||||||
* Sets up the fragment's UI components, including RecyclerView, search, and swipe-to-refresh.
|
* Sets up the fragment's UI components, including RecyclerView, search, and swipe-to-refresh.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_purchase_order, container, false);
|
binding = FragmentPurchaseOrderBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
setupRecyclerView(view);
|
setupRecyclerView();
|
||||||
setupSearch(view);
|
setupSearch();
|
||||||
setupSwipeRefresh(view);
|
setupSwipeRefresh();
|
||||||
loadData();
|
loadData();
|
||||||
|
|
||||||
ImageButton hamburger = view.findViewById(R.id.btnHamburgerPO);
|
binding.btnHamburgerPO.setOnClickListener(v -> {
|
||||||
hamburger.setOnClickListener(v -> {
|
|
||||||
Fragment parent = getParentFragment();
|
Fragment parent = getParentFragment();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
Fragment grandParent = parent.getParentFragment();
|
Fragment grandParent = parent.getParentFragment();
|
||||||
@@ -67,25 +65,29 @@ public class PurchaseOrderFragment extends Fragment
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the RecyclerView with a layout manager and adapter for purchase orders.
|
* Initializes the RecyclerView with a layout manager and adapter for purchase orders.
|
||||||
*/
|
*/
|
||||||
private void setupRecyclerView(View view) {
|
private void setupRecyclerView() {
|
||||||
RecyclerView rv = view.findViewById(R.id.recyclerViewPO);
|
|
||||||
adapter = new PurchaseOrderAdapter(filteredList, this);
|
adapter = new PurchaseOrderAdapter(filteredList, this);
|
||||||
rv.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewPO.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
rv.setAdapter(adapter);
|
binding.recyclerViewPO.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the search bar for filtering.
|
* Configures the search bar for filtering.
|
||||||
*/
|
*/
|
||||||
private void setupSearch(View view) {
|
private void setupSearch() {
|
||||||
etSearch = view.findViewById(R.id.etSearchPO);
|
binding.etSearchPO.addTextChangedListener(new TextWatcher() {
|
||||||
etSearch.addTextChangedListener(new TextWatcher() {
|
|
||||||
public void beforeTextChanged(CharSequence s, int a, int b, int c) {
|
public void beforeTextChanged(CharSequence s, int a, int b, int c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,9 +103,8 @@ public class PurchaseOrderFragment extends Fragment
|
|||||||
/**
|
/**
|
||||||
* Sets up the SwipeRefreshLayout to allow manual reloading of purchase order data.
|
* Sets up the SwipeRefreshLayout to allow manual reloading of purchase order data.
|
||||||
*/
|
*/
|
||||||
private void setupSwipeRefresh(View view) {
|
private void setupSwipeRefresh() {
|
||||||
swipeRefresh = view.findViewById(R.id.swipeRefreshPO);
|
binding.swipeRefreshPO.setOnRefreshListener(this::loadData);
|
||||||
swipeRefresh.setOnRefreshListener(this::loadData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,20 +138,20 @@ public class PurchaseOrderFragment extends Fragment
|
|||||||
switch (resource.status) {
|
switch (resource.status) {
|
||||||
case LOADING:
|
case LOADING:
|
||||||
// Show loading indicator
|
// Show loading indicator
|
||||||
if (swipeRefresh != null) swipeRefresh.setRefreshing(true);
|
binding.swipeRefreshPO.setRefreshing(true);
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
// Hide loading indicator and display data
|
// Hide loading indicator and display data
|
||||||
if (swipeRefresh != null) swipeRefresh.setRefreshing(false);
|
binding.swipeRefreshPO.setRefreshing(false);
|
||||||
if (resource.data != null) {
|
if (resource.data != null) {
|
||||||
poList.clear();
|
poList.clear();
|
||||||
poList.addAll(resource.data.getContent());
|
poList.addAll(resource.data.getContent());
|
||||||
filter(etSearch != null ? etSearch.getText().toString() : "");
|
filter(binding.etSearchPO != null ? binding.etSearchPO.getText().toString() : "");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
// Hide loading indicator and toast error message
|
// Hide loading indicator and toast error message
|
||||||
if (swipeRefresh != null) swipeRefresh.setRefreshing(false);
|
binding.swipeRefreshPO.setRefreshing(false);
|
||||||
Toast.makeText(getContext(), "Failed to load purchase orders: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Failed to load purchase orders: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
Log.e("POFragment", "Error loading purchase orders: " + resource.message);
|
Log.e("POFragment", "Error loading purchase orders: " + resource.message);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -2,23 +2,19 @@ package com.example.petstoremobile.fragments.listfragments;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.SaleAdapter;
|
import com.example.petstoremobile.adapters.SaleAdapter;
|
||||||
import com.example.petstoremobile.api.SaleApi;
|
import com.example.petstoremobile.api.SaleApi;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentSaleBinding;
|
||||||
import com.example.petstoremobile.fragments.ListFragment;
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
import com.example.petstoremobile.models.Sale;
|
import com.example.petstoremobile.models.Sale;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -31,46 +27,45 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickListener {
|
public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickListener {
|
||||||
|
|
||||||
|
private FragmentSaleBinding binding;
|
||||||
private List<Sale> saleList = new ArrayList<>();
|
private List<Sale> saleList = new ArrayList<>();
|
||||||
private List<Sale> filteredList = new ArrayList<>();
|
private List<Sale> filteredList = new ArrayList<>();
|
||||||
private SaleAdapter adapter;
|
private SaleAdapter adapter;
|
||||||
private SwipeRefreshLayout swipeRefreshLayout;
|
|
||||||
private EditText etSearch;
|
|
||||||
private ImageButton btnHamburger;
|
|
||||||
|
|
||||||
@Inject SaleApi api;
|
@Inject SaleApi api;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_sale, container, false);
|
binding = FragmentSaleBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
btnHamburger = view.findViewById(R.id.btnHamburger);
|
setupRecyclerView();
|
||||||
|
|
||||||
setupRecyclerView(view);
|
|
||||||
loadSaleData();
|
loadSaleData();
|
||||||
setupSearch(view);
|
setupSearch();
|
||||||
setupSwipeRefresh(view);
|
setupSwipeRefresh();
|
||||||
|
|
||||||
// Make the hamburger button open the drawer from listFragment
|
// Make the hamburger button open the drawer from listFragment
|
||||||
if (btnHamburger != null) {
|
binding.btnHamburger.setOnClickListener(v -> {
|
||||||
btnHamburger.setOnClickListener(v -> {
|
Fragment parent = getParentFragment();
|
||||||
Fragment parent = getParentFragment();
|
if (parent != null) {
|
||||||
if (parent != null) {
|
Fragment grandParent = parent.getParentFragment();
|
||||||
Fragment grandParent = parent.getParentFragment();
|
if (grandParent instanceof ListFragment) {
|
||||||
if (grandParent instanceof ListFragment) {
|
((ListFragment) grandParent).openDrawer();
|
||||||
((ListFragment) grandParent).openDrawer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupSearch(View view) {
|
@Override
|
||||||
etSearch = view.findViewById(R.id.etSearchSale);
|
public void onDestroyView() {
|
||||||
etSearch.addTextChangedListener(new TextWatcher() {
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupSearch() {
|
||||||
|
binding.etSearchSale.addTextChangedListener(new TextWatcher() {
|
||||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,11 +99,10 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
|
|||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupSwipeRefresh(View view) {
|
private void setupSwipeRefresh() {
|
||||||
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshSale);
|
binding.swipeRefreshSale.setOnRefreshListener(() -> {
|
||||||
swipeRefreshLayout.setOnRefreshListener(() -> {
|
|
||||||
loadSaleData();
|
loadSaleData();
|
||||||
swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshSale.setRefreshing(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,10 +137,9 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
|
|||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupRecyclerView(View view) {
|
private void setupRecyclerView() {
|
||||||
RecyclerView recyclerView = view.findViewById(R.id.recyclerViewSales);
|
|
||||||
adapter = new SaleAdapter(filteredList, this);
|
adapter = new SaleAdapter(filteredList, this);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewSales.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
recyclerView.setAdapter(adapter);
|
binding.recyclerViewSales.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
|
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
@@ -17,17 +15,14 @@ import android.util.Log;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.ServiceAdapter;
|
import com.example.petstoremobile.adapters.ServiceAdapter;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentServiceBinding;
|
||||||
import com.example.petstoremobile.dtos.ServiceDTO;
|
import com.example.petstoremobile.dtos.ServiceDTO;
|
||||||
import com.example.petstoremobile.fragments.ListFragment;
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
import com.example.petstoremobile.viewmodels.ServiceViewModel;
|
import com.example.petstoremobile.viewmodels.ServiceViewModel;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -37,13 +32,11 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class ServiceFragment extends Fragment implements ServiceAdapter.OnServiceClickListener {
|
public class ServiceFragment extends Fragment implements ServiceAdapter.OnServiceClickListener {
|
||||||
|
|
||||||
|
private FragmentServiceBinding binding;
|
||||||
private List<ServiceDTO> serviceList = new ArrayList<>();
|
private List<ServiceDTO> serviceList = new ArrayList<>();
|
||||||
private List<ServiceDTO> filteredList = new ArrayList<>();
|
private List<ServiceDTO> filteredList = new ArrayList<>();
|
||||||
private ServiceAdapter adapter;
|
private ServiceAdapter adapter;
|
||||||
private ImageButton hamburger;
|
|
||||||
private ServiceViewModel viewModel;
|
private ServiceViewModel viewModel;
|
||||||
private SwipeRefreshLayout swipeRefreshLayout;
|
|
||||||
private EditText etSearch;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the fragment and its associated ServiceViewModel.
|
* Initializes the fragment and its associated ServiceViewModel.
|
||||||
@@ -60,21 +53,18 @@ public class ServiceFragment extends Fragment implements ServiceAdapter.OnServic
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_service, container, false);
|
binding = FragmentServiceBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
hamburger = view.findViewById(R.id.btnHamburger);
|
setupRecyclerView();
|
||||||
|
setupSearch();
|
||||||
setupRecyclerView(view);
|
setupSwipeRefresh();
|
||||||
setupSearch(view);
|
|
||||||
setupSwipeRefresh(view);
|
|
||||||
loadServiceData();
|
loadServiceData();
|
||||||
|
|
||||||
//Add button to opens the add dialog
|
//Add button to opens the add dialog
|
||||||
FloatingActionButton fabAddService = view.findViewById(R.id.fabAddService);
|
binding.fabAddService.setOnClickListener(v -> openServiceDetails(-1));
|
||||||
fabAddService.setOnClickListener(v -> openServiceDetails(-1));
|
|
||||||
|
|
||||||
//Make the hamburger button open the drawer from listFragment
|
//Make the hamburger button open the drawer from listFragment
|
||||||
hamburger.setOnClickListener(v -> {
|
binding.btnHamburger.setOnClickListener(v -> {
|
||||||
Fragment parent = getParentFragment();
|
Fragment parent = getParentFragment();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
Fragment grandParent = parent.getParentFragment();
|
Fragment grandParent = parent.getParentFragment();
|
||||||
@@ -84,15 +74,20 @@ public class ServiceFragment extends Fragment implements ServiceAdapter.OnServic
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the search bar for filtering.
|
* Configures the search bar for filtering.
|
||||||
*/
|
*/
|
||||||
private void setupSearch(View view) {
|
private void setupSearch() {
|
||||||
etSearch = view.findViewById(R.id.etSearchService);
|
binding.etSearchService.addTextChangedListener(new TextWatcher() {
|
||||||
etSearch.addTextChangedListener(new TextWatcher() {
|
|
||||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
filterServices(s.toString());
|
filterServices(s.toString());
|
||||||
@@ -123,9 +118,8 @@ public class ServiceFragment extends Fragment implements ServiceAdapter.OnServic
|
|||||||
/**
|
/**
|
||||||
* Sets up the SwipeRefreshLayout to allow manual reloading of service data.
|
* Sets up the SwipeRefreshLayout to allow manual reloading of service data.
|
||||||
*/
|
*/
|
||||||
private void setupSwipeRefresh(View view) {
|
private void setupSwipeRefresh() {
|
||||||
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshService);
|
binding.swipeRefreshService.setOnRefreshListener(this::loadServiceData);
|
||||||
swipeRefreshLayout.setOnRefreshListener(this::loadServiceData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,20 +163,20 @@ public class ServiceFragment extends Fragment implements ServiceAdapter.OnServic
|
|||||||
switch (resource.status) {
|
switch (resource.status) {
|
||||||
case LOADING:
|
case LOADING:
|
||||||
// Show loading indicator
|
// Show loading indicator
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(true);
|
binding.swipeRefreshService.setRefreshing(true);
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
// Hide loading indicator and display data
|
// Hide loading indicator and display data
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshService.setRefreshing(false);
|
||||||
if (resource.data != null) {
|
if (resource.data != null) {
|
||||||
serviceList.clear();
|
serviceList.clear();
|
||||||
serviceList.addAll(resource.data.getContent());
|
serviceList.addAll(resource.data.getContent());
|
||||||
filterServices(etSearch != null ? etSearch.getText().toString() : "");
|
filterServices(binding.etSearchService != null ? binding.etSearchService.getText().toString() : "");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
// Hide loading indicator and toast error message
|
// Hide loading indicator and toast error message
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshService.setRefreshing(false);
|
||||||
if (getContext() != null) {
|
if (getContext() != null) {
|
||||||
Toast.makeText(getContext(), "Failed to load services: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Failed to load services: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
@@ -195,10 +189,9 @@ public class ServiceFragment extends Fragment implements ServiceAdapter.OnServic
|
|||||||
/**
|
/**
|
||||||
* Initializes the RecyclerView with a layout manager and adapter for services.
|
* Initializes the RecyclerView with a layout manager and adapter for services.
|
||||||
*/
|
*/
|
||||||
private void setupRecyclerView(View view) {
|
private void setupRecyclerView() {
|
||||||
RecyclerView recyclerView = view.findViewById(R.id.recyclerViewServices);
|
|
||||||
adapter = new ServiceAdapter(filteredList, this);
|
adapter = new ServiceAdapter(filteredList, this);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewServices.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
recyclerView.setAdapter(adapter);
|
binding.recyclerViewServices.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
|
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
@@ -17,17 +15,14 @@ import android.util.Log;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.SupplierAdapter;
|
import com.example.petstoremobile.adapters.SupplierAdapter;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentSupplierBinding;
|
||||||
import com.example.petstoremobile.dtos.SupplierDTO;
|
import com.example.petstoremobile.dtos.SupplierDTO;
|
||||||
import com.example.petstoremobile.fragments.ListFragment;
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
import com.example.petstoremobile.viewmodels.SupplierViewModel;
|
import com.example.petstoremobile.viewmodels.SupplierViewModel;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -37,13 +32,11 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupplierClickListener {
|
public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupplierClickListener {
|
||||||
|
|
||||||
|
private FragmentSupplierBinding binding;
|
||||||
private List<SupplierDTO> supplierList = new ArrayList<>();
|
private List<SupplierDTO> supplierList = new ArrayList<>();
|
||||||
private List<SupplierDTO> filteredList = new ArrayList<>();
|
private List<SupplierDTO> filteredList = new ArrayList<>();
|
||||||
private SupplierAdapter adapter;
|
private SupplierAdapter adapter;
|
||||||
private ImageButton hamburger;
|
|
||||||
private SupplierViewModel viewModel;
|
private SupplierViewModel viewModel;
|
||||||
private SwipeRefreshLayout swipeRefreshLayout;
|
|
||||||
private EditText etSearch;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the fragment and its associated SupplierViewModel.
|
* Initializes the fragment and its associated SupplierViewModel.
|
||||||
@@ -60,21 +53,18 @@ public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupp
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_supplier, container, false);
|
binding = FragmentSupplierBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
hamburger = view.findViewById(R.id.btnHamburger);
|
setupRecyclerView();
|
||||||
|
setupSearch();
|
||||||
setupRecyclerView(view);
|
setupSwipeRefresh();
|
||||||
setupSearch(view);
|
|
||||||
setupSwipeRefresh(view);
|
|
||||||
loadSupplierData();
|
loadSupplierData();
|
||||||
|
|
||||||
//Add button to opens the add dialog
|
//Add button to opens the add dialog
|
||||||
FloatingActionButton fabAddSupplier = view.findViewById(R.id.fabAddSupplier);
|
binding.fabAddSupplier.setOnClickListener(v -> openSupplierDetails(-1));
|
||||||
fabAddSupplier.setOnClickListener(v -> openSupplierDetails(-1));
|
|
||||||
|
|
||||||
//Make the hamburger button open the drawer from listFragment
|
//Make the hamburger button open the drawer from listFragment
|
||||||
hamburger.setOnClickListener(v -> {
|
binding.btnHamburger.setOnClickListener(v -> {
|
||||||
Fragment parent = getParentFragment();
|
Fragment parent = getParentFragment();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
Fragment grandParent = parent.getParentFragment();
|
Fragment grandParent = parent.getParentFragment();
|
||||||
@@ -84,15 +74,20 @@ public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupp
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the search bar for filtering.
|
* Configures the search bar for filtering.
|
||||||
*/
|
*/
|
||||||
private void setupSearch(View view) {
|
private void setupSearch() {
|
||||||
etSearch = view.findViewById(R.id.etSearchSupplier);
|
binding.etSearchSupplier.addTextChangedListener(new TextWatcher() {
|
||||||
etSearch.addTextChangedListener(new TextWatcher() {
|
|
||||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
filterSuppliers(s.toString());
|
filterSuppliers(s.toString());
|
||||||
@@ -124,9 +119,8 @@ public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupp
|
|||||||
/**
|
/**
|
||||||
* Sets up the SwipeRefreshLayout to allow manual reloading of supplier data.
|
* Sets up the SwipeRefreshLayout to allow manual reloading of supplier data.
|
||||||
*/
|
*/
|
||||||
private void setupSwipeRefresh(View view) {
|
private void setupSwipeRefresh() {
|
||||||
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshSupplier);
|
binding.swipeRefreshSupplier.setOnRefreshListener(this::loadSupplierData);
|
||||||
swipeRefreshLayout.setOnRefreshListener(this::loadSupplierData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -172,20 +166,20 @@ public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupp
|
|||||||
switch (resource.status) {
|
switch (resource.status) {
|
||||||
case LOADING:
|
case LOADING:
|
||||||
// Show loading indicator
|
// Show loading indicator
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(true);
|
binding.swipeRefreshSupplier.setRefreshing(true);
|
||||||
break;
|
break;
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
// Hide loading indicator and display data
|
// Hide loading indicator and display data
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshSupplier.setRefreshing(false);
|
||||||
if (resource.data != null) {
|
if (resource.data != null) {
|
||||||
supplierList.clear();
|
supplierList.clear();
|
||||||
supplierList.addAll(resource.data.getContent());
|
supplierList.addAll(resource.data.getContent());
|
||||||
filterSuppliers(etSearch.getText().toString());
|
filterSuppliers(binding.etSearchSupplier.getText().toString());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
// Hide loading indicator and toast error message
|
// Hide loading indicator and toast error message
|
||||||
if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);
|
binding.swipeRefreshSupplier.setRefreshing(false);
|
||||||
if (getContext() != null) {
|
if (getContext() != null) {
|
||||||
Toast.makeText(getContext(), "Failed to load suppliers: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Failed to load suppliers: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
@@ -198,10 +192,9 @@ public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupp
|
|||||||
/**
|
/**
|
||||||
* Initializes the RecyclerView with a layout manager and adapter for displaying suppliers.
|
* Initializes the RecyclerView with a layout manager and adapter for displaying suppliers.
|
||||||
*/
|
*/
|
||||||
private void setupRecyclerView(View view) {
|
private void setupRecyclerView() {
|
||||||
RecyclerView recyclerView = view.findViewById(R.id.recyclerViewSuppliers);
|
|
||||||
adapter = new SupplierAdapter(filteredList, this);
|
adapter = new SupplierAdapter(filteredList, this);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewSuppliers.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
recyclerView.setAdapter(adapter);
|
binding.recyclerViewSuppliers.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.example.petstoremobile.fragments.listfragments.detailfragments;
|
|||||||
|
|
||||||
import android.app.DatePickerDialog;
|
import android.app.DatePickerDialog;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
import android.widget.*;
|
import android.widget.*;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -10,7 +9,7 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.databinding.FragmentAdoptionDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.*;
|
import com.example.petstoremobile.dtos.*;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
@@ -29,10 +28,7 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class AdoptionDetailFragment extends Fragment {
|
public class AdoptionDetailFragment extends Fragment {
|
||||||
|
|
||||||
private TextView tvMode, tvAdoptionId;
|
private FragmentAdoptionDetailBinding binding;
|
||||||
private EditText etAdoptionDate;
|
|
||||||
private Spinner spinnerPet, spinnerCustomer, spinnerStatus;
|
|
||||||
private Button btnSave, btnDelete, btnBack;
|
|
||||||
|
|
||||||
private long adoptionId = -1;
|
private long adoptionId = -1;
|
||||||
private boolean isEditing = false;
|
private boolean isEditing = false;
|
||||||
@@ -59,49 +55,39 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_adoption_detail, container, false);
|
binding = FragmentAdoptionDetailBinding.inflate(inflater, container, false);
|
||||||
initViews(view);
|
|
||||||
setupSpinners();
|
setupSpinners();
|
||||||
setupDatePicker();
|
setupDatePicker();
|
||||||
loadData();
|
loadData();
|
||||||
handleArguments();
|
handleArguments();
|
||||||
|
|
||||||
btnBack.setOnClickListener(v -> navigateBack());
|
binding.btnAdoptionBack.setOnClickListener(v -> navigateBack());
|
||||||
btnSave.setOnClickListener(v -> saveAdoption());
|
binding.btnSaveAdoption.setOnClickListener(v -> saveAdoption());
|
||||||
btnDelete.setOnClickListener(v -> confirmDelete());
|
binding.btnDeleteAdoption.setOnClickListener(v -> confirmDelete());
|
||||||
return view;
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Initializes UI components from the layout.
|
public void onDestroyView() {
|
||||||
*/
|
super.onDestroyView();
|
||||||
private void initViews(View v) {
|
binding = null;
|
||||||
tvMode = v.findViewById(R.id.tvAdoptionMode);
|
|
||||||
tvAdoptionId = v.findViewById(R.id.tvAdoptionId);
|
|
||||||
etAdoptionDate = v.findViewById(R.id.etAdoptionDate);
|
|
||||||
spinnerPet = v.findViewById(R.id.spinnerAdoptionPet);
|
|
||||||
spinnerCustomer= v.findViewById(R.id.spinnerAdoptionCustomer);
|
|
||||||
spinnerStatus = v.findViewById(R.id.spinnerAdoptionStatus);
|
|
||||||
btnSave = v.findViewById(R.id.btnSaveAdoption);
|
|
||||||
btnDelete = v.findViewById(R.id.btnDeleteAdoption);
|
|
||||||
btnBack = v.findViewById(R.id.btnAdoptionBack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the spinner for adoption status.
|
* Configures the spinner for adoption status.
|
||||||
*/
|
*/
|
||||||
private void setupSpinners() {
|
private void setupSpinners() {
|
||||||
SpinnerUtils.setupStringSpinner(requireContext(), spinnerStatus, STATUSES);
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerAdoptionStatus, STATUSES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the date picker dialog for the adoption date field.
|
* Configures the date picker dialog for the adoption date field.
|
||||||
*/
|
*/
|
||||||
private void setupDatePicker() {
|
private void setupDatePicker() {
|
||||||
etAdoptionDate.setOnClickListener(v -> {
|
binding.etAdoptionDate.setOnClickListener(v -> {
|
||||||
Calendar c = Calendar.getInstance();
|
Calendar c = Calendar.getInstance();
|
||||||
new DatePickerDialog(requireContext(),
|
new DatePickerDialog(requireContext(),
|
||||||
(dp, y, m, d) -> etAdoptionDate.setText(
|
(dp, y, m, d) -> binding.etAdoptionDate.setText(
|
||||||
String.format("%04d-%02d-%02d", y, m + 1, d)),
|
String.format("%04d-%02d-%02d", y, m + 1, d)),
|
||||||
c.get(Calendar.YEAR),
|
c.get(Calendar.YEAR),
|
||||||
c.get(Calendar.MONTH),
|
c.get(Calendar.MONTH),
|
||||||
@@ -124,7 +110,7 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
petViewModel.getAllPets(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
petViewModel.getAllPets(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
petList = resource.data.getContent();
|
petList = resource.data.getContent();
|
||||||
SpinnerUtils.populateSpinner(requireContext(), spinnerPet, petList,
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionPet, petList,
|
||||||
PetDTO::getPetName, "-- Select Pet --",
|
PetDTO::getPetName, "-- Select Pet --",
|
||||||
preselectedPetId, PetDTO::getPetId);
|
preselectedPetId, PetDTO::getPetId);
|
||||||
}
|
}
|
||||||
@@ -138,7 +124,7 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
customerViewModel.getAllCustomers(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
customerViewModel.getAllCustomers(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
customerList = resource.data.getContent();
|
customerList = resource.data.getContent();
|
||||||
SpinnerUtils.populateSpinner(requireContext(), spinnerCustomer, customerList,
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionCustomer, customerList,
|
||||||
item -> item.getFirstName() + " " + item.getLastName(),
|
item -> item.getFirstName() + " " + item.getLastName(),
|
||||||
"-- Select Customer --",
|
"-- Select Customer --",
|
||||||
preselectedCustomerId, CustomerDTO::getCustomerId);
|
preselectedCustomerId, CustomerDTO::getCustomerId);
|
||||||
@@ -157,18 +143,18 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
preselectedPetId = a.getLong("petId", -1);
|
preselectedPetId = a.getLong("petId", -1);
|
||||||
preselectedCustomerId = a.getLong("customerId", -1);
|
preselectedCustomerId = a.getLong("customerId", -1);
|
||||||
|
|
||||||
tvMode.setText("Edit Adoption");
|
binding.tvAdoptionMode.setText("Edit Adoption");
|
||||||
tvAdoptionId.setText("ID: " + adoptionId);
|
binding.tvAdoptionId.setText("ID: " + adoptionId);
|
||||||
tvAdoptionId.setVisibility(View.VISIBLE);
|
binding.tvAdoptionId.setVisibility(View.VISIBLE);
|
||||||
etAdoptionDate.setText(a.getString("adoptionDate"));
|
binding.etAdoptionDate.setText(a.getString("adoptionDate"));
|
||||||
btnDelete.setVisibility(View.VISIBLE);
|
binding.btnDeleteAdoption.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
// Pre-fill status
|
// Pre-fill status
|
||||||
SpinnerUtils.setSelectionByValue(spinnerStatus, a.getString("adoptionStatus", "Pending"));
|
SpinnerUtils.setSelectionByValue(binding.spinnerAdoptionStatus, a.getString("adoptionStatus", "Pending"));
|
||||||
} else {
|
} else {
|
||||||
tvMode.setText("Add Adoption");
|
binding.tvAdoptionMode.setText("Add Adoption");
|
||||||
btnDelete.setVisibility(View.GONE);
|
binding.btnDeleteAdoption.setVisibility(View.GONE);
|
||||||
tvAdoptionId.setVisibility(View.GONE);
|
binding.tvAdoptionId.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,20 +162,20 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
* Validates input and saves the adoption request to the backend.
|
* Validates input and saves the adoption request to the backend.
|
||||||
*/
|
*/
|
||||||
private void saveAdoption() {
|
private void saveAdoption() {
|
||||||
if (spinnerCustomer.getSelectedItemPosition() == 0) {
|
if (binding.spinnerAdoptionCustomer.getSelectedItemPosition() == 0) {
|
||||||
Toast.makeText(getContext(), "Select a customer", Toast.LENGTH_SHORT).show(); return;
|
Toast.makeText(getContext(), "Select a customer", Toast.LENGTH_SHORT).show(); return;
|
||||||
}
|
}
|
||||||
if (spinnerPet.getSelectedItemPosition() == 0) {
|
if (binding.spinnerAdoptionPet.getSelectedItemPosition() == 0) {
|
||||||
Toast.makeText(getContext(), "Select a pet", Toast.LENGTH_SHORT).show(); return;
|
Toast.makeText(getContext(), "Select a pet", Toast.LENGTH_SHORT).show(); return;
|
||||||
}
|
}
|
||||||
String date = etAdoptionDate.getText().toString().trim();
|
String date = binding.etAdoptionDate.getText().toString().trim();
|
||||||
if (date.isEmpty()) {
|
if (date.isEmpty()) {
|
||||||
Toast.makeText(getContext(), "Select a date", Toast.LENGTH_SHORT).show(); return;
|
Toast.makeText(getContext(), "Select a date", Toast.LENGTH_SHORT).show(); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomerDTO customer = customerList.get(spinnerCustomer.getSelectedItemPosition() - 1);
|
CustomerDTO customer = customerList.get(binding.spinnerAdoptionCustomer.getSelectedItemPosition() - 1);
|
||||||
PetDTO pet = petList.get(spinnerPet.getSelectedItemPosition() - 1);
|
PetDTO pet = petList.get(binding.spinnerAdoptionPet.getSelectedItemPosition() - 1);
|
||||||
String status = STATUSES[spinnerStatus.getSelectedItemPosition()];
|
String status = STATUSES[binding.spinnerAdoptionStatus.getSelectedItemPosition()];
|
||||||
|
|
||||||
AdoptionDTO dto = new AdoptionDTO(
|
AdoptionDTO dto = new AdoptionDTO(
|
||||||
pet.getPetId(),
|
pet.getPetId(),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.databinding.FragmentAppointmentDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.*;
|
import com.example.petstoremobile.dtos.*;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
@@ -31,11 +31,7 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class AppointmentDetailFragment extends Fragment {
|
public class AppointmentDetailFragment extends Fragment {
|
||||||
|
|
||||||
private TextView tvMode, tvAppointmentId;
|
private FragmentAppointmentDetailBinding binding;
|
||||||
private EditText etAppointmentDate;
|
|
||||||
private Spinner spinnerPet, spinnerService, spinnerStatus, spinnerHour, spinnerMinute;
|
|
||||||
private Spinner spinnerCustomer, spinnerStore;
|
|
||||||
private Button btnSave, btnDelete, btnBack;
|
|
||||||
|
|
||||||
private long appointmentId = -1;
|
private long appointmentId = -1;
|
||||||
private boolean isEditing = false;
|
private boolean isEditing = false;
|
||||||
@@ -71,59 +67,45 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_appointment_detail, container, false);
|
binding = FragmentAppointmentDetailBinding.inflate(inflater, container, false);
|
||||||
initViews(view);
|
|
||||||
setupSpinners();
|
setupSpinners();
|
||||||
setupDatePicker();
|
setupDatePicker();
|
||||||
loadData();
|
loadData();
|
||||||
handleArguments();
|
handleArguments();
|
||||||
|
|
||||||
btnBack.setOnClickListener(v -> navigateBack());
|
binding.btnApptBack.setOnClickListener(v -> navigateBack());
|
||||||
btnSave.setOnClickListener(v -> saveAppointment());
|
binding.btnSaveAppointment.setOnClickListener(v -> saveAppointment());
|
||||||
btnDelete.setOnClickListener(v -> confirmDelete());
|
binding.btnDeleteAppointment.setOnClickListener(v -> confirmDelete());
|
||||||
return view;
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Initializes UI components from the layout.
|
public void onDestroyView() {
|
||||||
*/
|
super.onDestroyView();
|
||||||
private void initViews(View v) {
|
binding = null;
|
||||||
tvMode = v.findViewById(R.id.tvApptMode);
|
|
||||||
tvAppointmentId = v.findViewById(R.id.tvAppointmentId);
|
|
||||||
etAppointmentDate= v.findViewById(R.id.etAppointmentDate);
|
|
||||||
spinnerPet = v.findViewById(R.id.spinnerPet);
|
|
||||||
spinnerService = v.findViewById(R.id.spinnerService);
|
|
||||||
spinnerStatus = v.findViewById(R.id.spinnerAppointmentStatus);
|
|
||||||
spinnerHour = v.findViewById(R.id.spinnerHour);
|
|
||||||
spinnerMinute = v.findViewById(R.id.spinnerMinute);
|
|
||||||
spinnerCustomer = v.findViewById(R.id.spinnerCustomer);
|
|
||||||
spinnerStore = v.findViewById(R.id.spinnerStore);
|
|
||||||
btnSave = v.findViewById(R.id.btnSaveAppointment);
|
|
||||||
btnDelete = v.findViewById(R.id.btnDeleteAppointment);
|
|
||||||
btnBack = v.findViewById(R.id.btnApptBack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the adapters for spinners.
|
* Configures the adapters for spinners.
|
||||||
*/
|
*/
|
||||||
private void setupSpinners() {
|
private void setupSpinners() {
|
||||||
SpinnerUtils.setupStringSpinner(requireContext(), spinnerStatus, STATUSES);
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerAppointmentStatus, STATUSES);
|
||||||
|
|
||||||
String[] hours = new String[HOURS.length];
|
String[] hours = new String[HOURS.length];
|
||||||
for (int i = 0; i < HOURS.length; i++)
|
for (int i = 0; i < HOURS.length; i++)
|
||||||
hours[i] = String.format("%02d:00", HOURS[i]);
|
hours[i] = String.format("%02d:00", HOURS[i]);
|
||||||
SpinnerUtils.setupStringSpinner(requireContext(), spinnerHour, hours);
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerHour, hours);
|
||||||
SpinnerUtils.setupStringSpinner(requireContext(), spinnerMinute, new String[]{"00","15","30","45"});
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerMinute, new String[]{"00","15","30","45"});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the date picker dialog for the appointment date field.
|
* Configures the date picker dialog for the appointment date field.
|
||||||
*/
|
*/
|
||||||
private void setupDatePicker() {
|
private void setupDatePicker() {
|
||||||
etAppointmentDate.setOnClickListener(v -> {
|
binding.etAppointmentDate.setOnClickListener(v -> {
|
||||||
Calendar c = Calendar.getInstance();
|
Calendar c = Calendar.getInstance();
|
||||||
DatePickerDialog d = new DatePickerDialog(requireContext(),
|
DatePickerDialog d = new DatePickerDialog(requireContext(),
|
||||||
(dp,y,m,d1) -> etAppointmentDate.setText(
|
(dp,y,m,d1) -> binding.etAppointmentDate.setText(
|
||||||
String.format("%04d-%02d-%02d", y, m+1, d1)),
|
String.format("%04d-%02d-%02d", y, m+1, d1)),
|
||||||
c.get(Calendar.YEAR), c.get(Calendar.MONTH),
|
c.get(Calendar.YEAR), c.get(Calendar.MONTH),
|
||||||
c.get(Calendar.DAY_OF_MONTH));
|
c.get(Calendar.DAY_OF_MONTH));
|
||||||
@@ -149,7 +131,7 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
petViewModel.getAllPets(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
petViewModel.getAllPets(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
petList = resource.data.getContent();
|
petList = resource.data.getContent();
|
||||||
SpinnerUtils.populateSpinner(requireContext(), spinnerPet, petList,
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerPet, petList,
|
||||||
PetDTO::getPetName, "-- Select Pet --",
|
PetDTO::getPetName, "-- Select Pet --",
|
||||||
preselectedPetId, PetDTO::getPetId);
|
preselectedPetId, PetDTO::getPetId);
|
||||||
}
|
}
|
||||||
@@ -163,7 +145,7 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
serviceViewModel.getAllServices(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
serviceViewModel.getAllServices(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
serviceList = resource.data.getContent();
|
serviceList = resource.data.getContent();
|
||||||
SpinnerUtils.populateSpinner(requireContext(), spinnerService, serviceList,
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerService, serviceList,
|
||||||
ServiceDTO::getServiceName, "-- Select Service --",
|
ServiceDTO::getServiceName, "-- Select Service --",
|
||||||
preselectedServiceId, ServiceDTO::getServiceId);
|
preselectedServiceId, ServiceDTO::getServiceId);
|
||||||
}
|
}
|
||||||
@@ -177,7 +159,7 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
customerViewModel.getAllCustomers(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
customerViewModel.getAllCustomers(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
customerList = resource.data.getContent();
|
customerList = resource.data.getContent();
|
||||||
SpinnerUtils.populateSpinner(requireContext(), spinnerCustomer, customerList,
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerCustomer, customerList,
|
||||||
item -> item.getFirstName() + " " + item.getLastName(),
|
item -> item.getFirstName() + " " + item.getLastName(),
|
||||||
"-- Select Customer --",
|
"-- Select Customer --",
|
||||||
preselectedCustomerId, CustomerDTO::getCustomerId);
|
preselectedCustomerId, CustomerDTO::getCustomerId);
|
||||||
@@ -192,7 +174,7 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
storeViewModel.getAllStores(0, 50).observe(getViewLifecycleOwner(), resource -> {
|
storeViewModel.getAllStores(0, 50).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
storeList = resource.data.getContent();
|
storeList = resource.data.getContent();
|
||||||
SpinnerUtils.populateSpinner(requireContext(), spinnerStore, storeList,
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerStore, storeList,
|
||||||
StoreDTO::getStoreName, "-- Select Store --",
|
StoreDTO::getStoreName, "-- Select Store --",
|
||||||
preselectedStoreId, StoreDTO::getStoreId);
|
preselectedStoreId, StoreDTO::getStoreId);
|
||||||
}
|
}
|
||||||
@@ -212,11 +194,11 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
preselectedCustomerId = a.getLong("customerId", -1);
|
preselectedCustomerId = a.getLong("customerId", -1);
|
||||||
preselectedStoreId = a.getLong("storeId", -1);
|
preselectedStoreId = a.getLong("storeId", -1);
|
||||||
|
|
||||||
tvMode.setText("Edit Appointment");
|
binding.tvApptMode.setText("Edit Appointment");
|
||||||
tvAppointmentId.setText("ID: " + appointmentId);
|
binding.tvAppointmentId.setText("ID: " + appointmentId);
|
||||||
tvAppointmentId.setVisibility(View.VISIBLE);
|
binding.tvAppointmentId.setVisibility(View.VISIBLE);
|
||||||
etAppointmentDate.setText(a.getString("appointmentDate"));
|
binding.etAppointmentDate.setText(a.getString("appointmentDate"));
|
||||||
btnDelete.setVisibility(View.VISIBLE);
|
binding.btnDeleteAppointment.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
// Pre-fill time spinners
|
// Pre-fill time spinners
|
||||||
String time = a.getString("appointmentTime", "09:00");
|
String time = a.getString("appointmentTime", "09:00");
|
||||||
@@ -226,18 +208,18 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
int hour = Integer.parseInt(parts[0]);
|
int hour = Integer.parseInt(parts[0]);
|
||||||
int min = Integer.parseInt(parts[1]);
|
int min = Integer.parseInt(parts[1]);
|
||||||
for (int i = 0; i < HOURS.length; i++)
|
for (int i = 0; i < HOURS.length; i++)
|
||||||
if (HOURS[i] == hour) { spinnerHour.setSelection(i); break; }
|
if (HOURS[i] == hour) { binding.spinnerHour.setSelection(i); break; }
|
||||||
for (int i = 0; i < MINUTES.length; i++)
|
for (int i = 0; i < MINUTES.length; i++)
|
||||||
if (MINUTES[i] == min) { spinnerMinute.setSelection(i); break; }
|
if (MINUTES[i] == min) { binding.spinnerMinute.setSelection(i); break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre-fill status
|
// Pre-fill status
|
||||||
SpinnerUtils.setSelectionByValue(spinnerStatus, a.getString("appointmentStatus", "Booked"));
|
SpinnerUtils.setSelectionByValue(binding.spinnerAppointmentStatus, a.getString("appointmentStatus", "Booked"));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
tvMode.setText("Add Appointment");
|
binding.tvApptMode.setText("Add Appointment");
|
||||||
btnDelete.setVisibility(View.GONE);
|
binding.btnDeleteAppointment.setVisibility(View.GONE);
|
||||||
tvAppointmentId.setVisibility(View.GONE);
|
binding.tvAppointmentId.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,32 +227,32 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
* Validates input and saves the appointment to the backend.
|
* Validates input and saves the appointment to the backend.
|
||||||
*/
|
*/
|
||||||
private void saveAppointment() {
|
private void saveAppointment() {
|
||||||
if (spinnerCustomer.getSelectedItemPosition() == 0) {
|
if (binding.spinnerCustomer.getSelectedItemPosition() == 0) {
|
||||||
Toast.makeText(getContext(), "Select a customer", Toast.LENGTH_SHORT).show(); return;
|
Toast.makeText(getContext(), "Select a customer", Toast.LENGTH_SHORT).show(); return;
|
||||||
}
|
}
|
||||||
if (spinnerStore.getSelectedItemPosition() == 0) {
|
if (binding.spinnerStore.getSelectedItemPosition() == 0) {
|
||||||
Toast.makeText(getContext(), "Select a store", Toast.LENGTH_SHORT).show(); return;
|
Toast.makeText(getContext(), "Select a store", Toast.LENGTH_SHORT).show(); return;
|
||||||
}
|
}
|
||||||
if (spinnerPet.getSelectedItemPosition() == 0) {
|
if (binding.spinnerPet.getSelectedItemPosition() == 0) {
|
||||||
Toast.makeText(getContext(), "Select a pet", Toast.LENGTH_SHORT).show(); return;
|
Toast.makeText(getContext(), "Select a pet", Toast.LENGTH_SHORT).show(); return;
|
||||||
}
|
}
|
||||||
if (spinnerService.getSelectedItemPosition() == 0) {
|
if (binding.spinnerService.getSelectedItemPosition() == 0) {
|
||||||
Toast.makeText(getContext(), "Select a service", Toast.LENGTH_SHORT).show(); return;
|
Toast.makeText(getContext(), "Select a service", Toast.LENGTH_SHORT).show(); return;
|
||||||
}
|
}
|
||||||
String date = etAppointmentDate.getText().toString().trim();
|
String date = binding.etAppointmentDate.getText().toString().trim();
|
||||||
if (date.isEmpty()) {
|
if (date.isEmpty()) {
|
||||||
Toast.makeText(getContext(), "Select a date", Toast.LENGTH_SHORT).show(); return;
|
Toast.makeText(getContext(), "Select a date", Toast.LENGTH_SHORT).show(); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomerDTO customer = customerList.get(spinnerCustomer.getSelectedItemPosition() - 1);
|
CustomerDTO customer = customerList.get(binding.spinnerCustomer.getSelectedItemPosition() - 1);
|
||||||
StoreDTO store = storeList.get(spinnerStore.getSelectedItemPosition() - 1);
|
StoreDTO store = storeList.get(binding.spinnerStore.getSelectedItemPosition() - 1);
|
||||||
PetDTO pet = petList.get(spinnerPet.getSelectedItemPosition() - 1);
|
PetDTO pet = petList.get(binding.spinnerPet.getSelectedItemPosition() - 1);
|
||||||
ServiceDTO service = serviceList.get(spinnerService.getSelectedItemPosition() - 1);
|
ServiceDTO service = serviceList.get(binding.spinnerService.getSelectedItemPosition() - 1);
|
||||||
|
|
||||||
String time = String.format("%02d:%02d",
|
String time = String.format("%02d:%02d",
|
||||||
HOURS[spinnerHour.getSelectedItemPosition()],
|
HOURS[binding.spinnerHour.getSelectedItemPosition()],
|
||||||
MINUTES[spinnerMinute.getSelectedItemPosition()]);
|
MINUTES[binding.spinnerMinute.getSelectedItemPosition()]);
|
||||||
String status = STATUSES[spinnerStatus.getSelectedItemPosition()];
|
String status = STATUSES[binding.spinnerAppointmentStatus.getSelectedItemPosition()];
|
||||||
|
|
||||||
|
|
||||||
// Validate future date+time if status is Booked
|
// Validate future date+time if status is Booked
|
||||||
|
|||||||
@@ -9,9 +9,6 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.AutoCompleteTextView;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -20,9 +17,8 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
|
||||||
import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
|
import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
|
||||||
import com.example.petstoremobile.dtos.InventoryDTO;
|
import com.example.petstoremobile.databinding.FragmentInventoryDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.InventoryRequest;
|
import com.example.petstoremobile.dtos.InventoryRequest;
|
||||||
import com.example.petstoremobile.dtos.ProductDTO;
|
import com.example.petstoremobile.dtos.ProductDTO;
|
||||||
import com.example.petstoremobile.utils.InputValidator;
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
@@ -41,10 +37,7 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class InventoryDetailFragment extends Fragment {
|
public class InventoryDetailFragment extends Fragment {
|
||||||
|
|
||||||
private TextView tvMode, tvInventoryId, tvProductInfo;
|
private FragmentInventoryDetailBinding binding;
|
||||||
private AutoCompleteTextView etProductSearch;
|
|
||||||
private android.widget.EditText etQuantity;
|
|
||||||
private Button btnSave, btnDelete, btnBack;
|
|
||||||
|
|
||||||
private InventoryViewModel inventoryViewModel;
|
private InventoryViewModel inventoryViewModel;
|
||||||
private ProductViewModel productViewModel;
|
private ProductViewModel productViewModel;
|
||||||
@@ -73,44 +66,35 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_inventory_detail, container, false);
|
binding = FragmentInventoryDetailBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
initViews(view);
|
|
||||||
setupProductSearch();
|
setupProductSearch();
|
||||||
handleArguments();
|
handleArguments();
|
||||||
|
|
||||||
btnBack.setOnClickListener(v -> navigateBack());
|
binding.btnInventoryBack.setOnClickListener(v -> navigateBack());
|
||||||
btnSave.setOnClickListener(v -> saveInventory());
|
binding.btnSaveInventory.setOnClickListener(v -> saveInventory());
|
||||||
btnDelete.setOnClickListener(v -> confirmDelete());
|
binding.btnDeleteInventory.setOnClickListener(v -> confirmDelete());
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the layout view and set adapter.
|
|
||||||
*/
|
|
||||||
private void initViews(View view) {
|
|
||||||
tvMode = view.findViewById(R.id.tvInventoryMode);
|
|
||||||
tvInventoryId = view.findViewById(R.id.tvInventoryId);
|
|
||||||
tvProductInfo = view.findViewById(R.id.tvProductInfo);
|
|
||||||
etProductSearch = view.findViewById(R.id.etProductSearch);
|
|
||||||
etQuantity = view.findViewById(R.id.etQuantity);
|
|
||||||
btnSave = view.findViewById(R.id.btnSaveInventory);
|
|
||||||
btnDelete = view.findViewById(R.id.btnDeleteInventory);
|
|
||||||
btnBack = view.findViewById(R.id.btnInventoryBack);
|
|
||||||
|
|
||||||
// Setup dropdown adapter
|
// Setup dropdown adapter
|
||||||
dropdownAdapter = new BlackTextArrayAdapter<>(requireContext(),
|
dropdownAdapter = new BlackTextArrayAdapter<>(requireContext(),
|
||||||
android.R.layout.simple_dropdown_item_1line, new ArrayList<>());
|
android.R.layout.simple_dropdown_item_1line, new ArrayList<>());
|
||||||
etProductSearch.setAdapter(dropdownAdapter);
|
binding.etProductSearch.setAdapter(dropdownAdapter);
|
||||||
etProductSearch.setThreshold(1); // start showing after 1 character
|
binding.etProductSearch.setThreshold(1); // start showing after 1 character
|
||||||
|
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* setup the product search dropdown.
|
* setup the product search dropdown.
|
||||||
*/
|
*/
|
||||||
private void setupProductSearch() {
|
private void setupProductSearch() {
|
||||||
etProductSearch.addTextChangedListener(new TextWatcher() {
|
binding.etProductSearch.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int i, int i1, int i2) {
|
public void beforeTextChanged(CharSequence s, int i, int i1, int i2) {
|
||||||
}
|
}
|
||||||
@@ -123,7 +107,7 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
// Clear selected product when user is typing again
|
// Clear selected product when user is typing again
|
||||||
selectedProduct = null;
|
selectedProduct = null;
|
||||||
tvProductInfo.setVisibility(View.GONE);
|
binding.tvProductInfo.setVisibility(View.GONE);
|
||||||
|
|
||||||
if (searchRunnable != null)
|
if (searchRunnable != null)
|
||||||
searchHandler.removeCallbacks(searchRunnable);
|
searchHandler.removeCallbacks(searchRunnable);
|
||||||
@@ -137,14 +121,14 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// When user picks an item from the dropdown
|
// When user picks an item from the dropdown
|
||||||
etProductSearch.setOnItemClickListener((parent, view, position, id) -> {
|
binding.etProductSearch.setOnItemClickListener((parent, view, position, id) -> {
|
||||||
if (position < productSuggestions.size()) {
|
if (position < productSuggestions.size()) {
|
||||||
selectedProduct = productSuggestions.get(position);
|
selectedProduct = productSuggestions.get(position);
|
||||||
// Show product details below the search box
|
// Show product details below the search box
|
||||||
tvProductInfo.setText(
|
binding.tvProductInfo.setText(
|
||||||
"ID: " + selectedProduct.getProdId()
|
"ID: " + selectedProduct.getProdId()
|
||||||
+ " • " + selectedProduct.getCategoryName());
|
+ " • " + selectedProduct.getCategoryName());
|
||||||
tvProductInfo.setVisibility(View.VISIBLE);
|
binding.tvProductInfo.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -167,7 +151,7 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
dropdownAdapter.clear();
|
dropdownAdapter.clear();
|
||||||
dropdownAdapter.addAll(names);
|
dropdownAdapter.addAll(names);
|
||||||
dropdownAdapter.notifyDataSetChanged();
|
dropdownAdapter.notifyDataSetChanged();
|
||||||
etProductSearch.showDropDown();
|
binding.etProductSearch.showDropDown();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -181,37 +165,37 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
isEditing = true;
|
isEditing = true;
|
||||||
inventoryId = args.getLong("inventoryId");
|
inventoryId = args.getLong("inventoryId");
|
||||||
|
|
||||||
tvMode.setText("Edit Inventory");
|
binding.tvInventoryMode.setText("Edit Inventory");
|
||||||
tvInventoryId.setText("Inventory ID: " + inventoryId);
|
binding.tvInventoryId.setText("Inventory ID: " + inventoryId);
|
||||||
tvInventoryId.setVisibility(View.VISIBLE);
|
binding.tvInventoryId.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
// Pre-fill search box with existing product name
|
// Pre-fill search box with existing product name
|
||||||
String productName = args.getString("productName", "");
|
String productName = args.getString("productName", "");
|
||||||
long prodId = args.getLong("prodId", -1);
|
long prodId = args.getLong("prodId", -1);
|
||||||
etProductSearch.setText(productName);
|
binding.etProductSearch.setText(productName);
|
||||||
|
|
||||||
// Show existing product info
|
// Show existing product info
|
||||||
if (prodId != -1) {
|
if (prodId != -1) {
|
||||||
tvProductInfo.setText(
|
binding.tvProductInfo.setText(
|
||||||
"ID: " + prodId
|
"ID: " + prodId
|
||||||
+ " • " + args.getString("categoryName", ""));
|
+ " • " + args.getString("categoryName", ""));
|
||||||
tvProductInfo.setVisibility(View.VISIBLE);
|
binding.tvProductInfo.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
// Build a minimal ProductDTO so selectedProduct is not null on save
|
// Build a minimal ProductDTO so selectedProduct is not null on save
|
||||||
selectedProduct = new ProductDTO(productName, null, null, null);
|
selectedProduct = new ProductDTO(productName, null, null, null);
|
||||||
selectedProduct.setProdId(prodId);
|
selectedProduct.setProdId(prodId);
|
||||||
}
|
}
|
||||||
|
|
||||||
etQuantity.setText(String.valueOf(args.getInt("quantity", 0)));
|
binding.etQuantity.setText(String.valueOf(args.getInt("quantity", 0)));
|
||||||
btnDelete.setVisibility(View.VISIBLE);
|
binding.btnDeleteInventory.setVisibility(View.VISIBLE);
|
||||||
btnSave.setText("Save");
|
binding.btnSaveInventory.setText("Save");
|
||||||
} else {
|
} else {
|
||||||
isEditing = false;
|
isEditing = false;
|
||||||
tvMode.setText("Add Inventory");
|
binding.tvInventoryMode.setText("Add Inventory");
|
||||||
tvInventoryId.setVisibility(View.GONE);
|
binding.tvInventoryId.setVisibility(View.GONE);
|
||||||
tvProductInfo.setVisibility(View.GONE);
|
binding.tvProductInfo.setVisibility(View.GONE);
|
||||||
btnDelete.setVisibility(View.GONE);
|
binding.btnDeleteInventory.setVisibility(View.GONE);
|
||||||
btnSave.setText("Add");
|
binding.btnSaveInventory.setText("Add");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,17 +204,17 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
*/
|
*/
|
||||||
private void saveInventory() {
|
private void saveInventory() {
|
||||||
if (selectedProduct == null) {
|
if (selectedProduct == null) {
|
||||||
etProductSearch.setError("Please select a product from the list");
|
binding.etProductSearch.setError("Please select a product from the list");
|
||||||
etProductSearch.requestFocus();
|
binding.etProductSearch.requestFocus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InputValidator.isNotEmpty(etQuantity, "Quantity") ||
|
if (!InputValidator.isNotEmpty(binding.etQuantity, "Quantity") ||
|
||||||
!InputValidator.isPositiveInteger(etQuantity, "Quantity")) {
|
!InputValidator.isPositiveInteger(binding.etQuantity, "Quantity")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int quantity = Integer.parseInt(etQuantity.getText().toString().trim());
|
int quantity = Integer.parseInt(binding.etQuantity.getText().toString().trim());
|
||||||
|
|
||||||
InventoryRequest request = new InventoryRequest(selectedProduct.getProdId(), quantity);
|
InventoryRequest request = new InventoryRequest(selectedProduct.getProdId(), quantity);
|
||||||
setButtonsEnabled(false);
|
setButtonsEnabled(false);
|
||||||
@@ -297,8 +281,8 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
* Enables or disables action buttons.
|
* Enables or disables action buttons.
|
||||||
*/
|
*/
|
||||||
private void setButtonsEnabled(boolean enabled) {
|
private void setButtonsEnabled(boolean enabled) {
|
||||||
btnSave.setEnabled(enabled);
|
binding.btnSaveInventory.setEnabled(enabled);
|
||||||
btnDelete.setEnabled(enabled);
|
binding.btnDeleteInventory.setEnabled(enabled);
|
||||||
btnBack.setEnabled(enabled);
|
binding.btnInventoryBack.setEnabled(enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,10 @@ import androidx.navigation.fragment.NavHostFragment;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentPetDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.PetDTO;
|
import com.example.petstoremobile.dtos.PetDTO;
|
||||||
import com.example.petstoremobile.utils.ActivityLogger;
|
import com.example.petstoremobile.utils.ActivityLogger;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
@@ -33,10 +30,7 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class PetDetailFragment extends Fragment {
|
public class PetDetailFragment extends Fragment {
|
||||||
|
|
||||||
private TextView tvMode, tvPetId;
|
private FragmentPetDetailBinding binding;
|
||||||
private EditText etPetName, etPetSpecies, etPetBreed, etPetAge, etPetPrice;
|
|
||||||
private Spinner spinnerPetStatus;
|
|
||||||
private Button btnSavePet, btnDeletePet, btnBack;
|
|
||||||
private int petId;
|
private int petId;
|
||||||
private boolean isEditing = false;
|
private boolean isEditing = false;
|
||||||
|
|
||||||
@@ -49,21 +43,25 @@ public class PetDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_pet_detail, container, false);
|
binding = FragmentPetDetailBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
//set up spinner and get controls from layout and display the view depending on the mode
|
|
||||||
initViews(view);
|
|
||||||
setupSpinner();
|
setupSpinner();
|
||||||
handleArguments();
|
handleArguments();
|
||||||
|
|
||||||
//set button click listeners
|
//set button click listeners
|
||||||
btnBack.setOnClickListener(v -> navigateBack());
|
binding.btnBack.setOnClickListener(v -> navigateBack());
|
||||||
btnSavePet.setOnClickListener(v -> savePet());
|
binding.btnSavePet.setOnClickListener(v -> savePet());
|
||||||
btnDeletePet.setOnClickListener(v -> deletePet());
|
binding.btnDeletePet.setOnClickListener(v -> deletePet());
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,19 +69,19 @@ public class PetDetailFragment extends Fragment {
|
|||||||
*/
|
*/
|
||||||
private void savePet() {
|
private void savePet() {
|
||||||
// Validates all fields using InputValidator
|
// Validates all fields using InputValidator
|
||||||
if (!InputValidator.isNotEmpty(etPetName, "Pet Name")) return;
|
if (!InputValidator.isNotEmpty(binding.etPetName, "Pet Name")) return;
|
||||||
if (!InputValidator.isNotEmpty(etPetSpecies, "Species")) return;
|
if (!InputValidator.isNotEmpty(binding.etPetSpecies, "Species")) return;
|
||||||
if (!InputValidator.isNotEmpty(etPetBreed, "Breed")) return;
|
if (!InputValidator.isNotEmpty(binding.etPetBreed, "Breed")) return;
|
||||||
if (!InputValidator.isPositiveInteger(etPetAge, "Age")) return;
|
if (!InputValidator.isPositiveInteger(binding.etPetAge, "Age")) return;
|
||||||
if (!InputValidator.isPositiveDecimal(etPetPrice, "Price")) return;
|
if (!InputValidator.isPositiveDecimal(binding.etPetPrice, "Price")) return;
|
||||||
|
|
||||||
//get all the values from the fields
|
//get all the values from the fields
|
||||||
String name = etPetName.getText().toString().trim();
|
String name = binding.etPetName.getText().toString().trim();
|
||||||
String species = etPetSpecies.getText().toString().trim();
|
String species = binding.etPetSpecies.getText().toString().trim();
|
||||||
String breed = etPetBreed.getText().toString().trim();
|
String breed = binding.etPetBreed.getText().toString().trim();
|
||||||
int age = Integer.parseInt(etPetAge.getText().toString().trim());
|
int age = Integer.parseInt(binding.etPetAge.getText().toString().trim());
|
||||||
String priceStr = etPetPrice.getText().toString().trim();
|
String priceStr = binding.etPetPrice.getText().toString().trim();
|
||||||
String status = spinnerPetStatus.getSelectedItem().toString();
|
String status = binding.spinnerPetStatus.getSelectedItem().toString();
|
||||||
|
|
||||||
//create a pet object to send to the API
|
//create a pet object to send to the API
|
||||||
PetDTO petDTO = new PetDTO();
|
PetDTO petDTO = new PetDTO();
|
||||||
@@ -160,48 +158,31 @@ public class PetDetailFragment extends Fragment {
|
|||||||
// Get pet data from arguments and populate fields
|
// Get pet data from arguments and populate fields
|
||||||
isEditing = true;
|
isEditing = true;
|
||||||
petId = getArguments().getInt("petId");
|
petId = getArguments().getInt("petId");
|
||||||
tvMode.setText("Edit Pet");
|
binding.tvMode.setText("Edit Pet");
|
||||||
tvPetId.setText("ID: " + petId);
|
binding.tvPetId.setText("ID: " + petId);
|
||||||
etPetName.setText(getArguments().getString("petName"));
|
binding.etPetName.setText(getArguments().getString("petName"));
|
||||||
etPetSpecies.setText(getArguments().getString("petSpecies"));
|
binding.etPetSpecies.setText(getArguments().getString("petSpecies"));
|
||||||
etPetBreed.setText(getArguments().getString("petBreed"));
|
binding.etPetBreed.setText(getArguments().getString("petBreed"));
|
||||||
etPetAge.setText(String.valueOf(getArguments().getInt("petAge")));
|
binding.etPetAge.setText(String.valueOf(getArguments().getInt("petAge")));
|
||||||
etPetPrice.setText(String.valueOf(getArguments().getDouble("petPrice")));
|
binding.etPetPrice.setText(String.valueOf(getArguments().getDouble("petPrice")));
|
||||||
SpinnerUtils.setSelectionByValue(spinnerPetStatus, getArguments().getString("petStatus"));
|
SpinnerUtils.setSelectionByValue(binding.spinnerPetStatus, getArguments().getString("petStatus"));
|
||||||
btnDeletePet.setVisibility(View.VISIBLE);
|
binding.btnDeletePet.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
// Pet is being added
|
// Pet is being added
|
||||||
// Set default values for add a new pet
|
// Set default values for add a new pet
|
||||||
isEditing = false;
|
isEditing = false;
|
||||||
tvMode.setText("Add Pet");
|
binding.tvMode.setText("Add Pet");
|
||||||
tvPetId.setVisibility(View.GONE);
|
binding.tvPetId.setVisibility(View.GONE);
|
||||||
btnDeletePet.setVisibility(View.GONE);
|
binding.btnDeletePet.setVisibility(View.GONE);
|
||||||
btnSavePet.setText("Add");
|
binding.btnSavePet.setText("Add");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds UI components from the layout.
|
|
||||||
*/
|
|
||||||
private void initViews(View view) {
|
|
||||||
tvMode = view.findViewById(R.id.tvMode);
|
|
||||||
tvPetId = view.findViewById(R.id.tvPetId);
|
|
||||||
etPetName = view.findViewById(R.id.etPetName);
|
|
||||||
etPetSpecies = view.findViewById(R.id.etPetSpecies);
|
|
||||||
etPetBreed = view.findViewById(R.id.etPetBreed);
|
|
||||||
etPetAge = view.findViewById(R.id.etPetAge);
|
|
||||||
etPetPrice = view.findViewById(R.id.etPetPrice);
|
|
||||||
spinnerPetStatus = view.findViewById(R.id.spinnerPetStatus);
|
|
||||||
btnSavePet = view.findViewById(R.id.btnSavePet);
|
|
||||||
btnDeletePet = view.findViewById(R.id.btnDeletePet);
|
|
||||||
btnBack = view.findViewById(R.id.btnBack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the spinner for pet status selection.
|
* Initializes the spinner for pet status selection.
|
||||||
*/
|
*/
|
||||||
private void setupSpinner() {
|
private void setupSpinner() {
|
||||||
SpinnerUtils.setupStringSpinner(requireContext(), spinnerPetStatus,
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerPetStatus,
|
||||||
new String[]{"Available", "Adopted"});
|
new String[]{"Available", "Adopted"});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import com.bumptech.glide.Glide;
|
|||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.api.*;
|
import com.example.petstoremobile.api.*;
|
||||||
import com.example.petstoremobile.api.auth.TokenManager;
|
import com.example.petstoremobile.api.auth.TokenManager;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentProductDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.*;
|
import com.example.petstoremobile.dtos.*;
|
||||||
import com.example.petstoremobile.viewmodels.ProductViewModel;
|
import com.example.petstoremobile.viewmodels.ProductViewModel;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
import com.example.petstoremobile.utils.ErrorUtils;
|
|
||||||
import com.example.petstoremobile.utils.FileUtils;
|
import com.example.petstoremobile.utils.FileUtils;
|
||||||
import com.example.petstoremobile.utils.GlideUtils;
|
import com.example.petstoremobile.utils.GlideUtils;
|
||||||
import com.example.petstoremobile.utils.ImagePickerHelper;
|
import com.example.petstoremobile.utils.ImagePickerHelper;
|
||||||
@@ -42,11 +42,7 @@ import okhttp3.RequestBody;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class ProductDetailFragment extends Fragment {
|
public class ProductDetailFragment extends Fragment {
|
||||||
|
|
||||||
private TextView tvMode, tvProductId;
|
private FragmentProductDetailBinding binding;
|
||||||
private EditText etProductName, etProductDesc, etProductPrice;
|
|
||||||
private Spinner spinnerCategory;
|
|
||||||
private Button btnSave, btnDelete, btnBack;
|
|
||||||
private ImageView ivProductImage;
|
|
||||||
|
|
||||||
private long prodId = -1;
|
private long prodId = -1;
|
||||||
private boolean isEditing = false;
|
private boolean isEditing = false;
|
||||||
@@ -75,7 +71,7 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onImagePicked(Uri uri) {
|
public void onImagePicked(Uri uri) {
|
||||||
photoUri = uri;
|
photoUri = uri;
|
||||||
Glide.with(ProductDetailFragment.this).load(uri).into(ivProductImage);
|
Glide.with(ProductDetailFragment.this).load(uri).into(binding.ivProductImage);
|
||||||
hasImage = true;
|
hasImage = true;
|
||||||
isImageChanged = true;
|
isImageChanged = true;
|
||||||
isImageRemoved = false;
|
isImageRemoved = false;
|
||||||
@@ -87,7 +83,7 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
hasImage = false;
|
hasImage = false;
|
||||||
isImageChanged = false;
|
isImageChanged = false;
|
||||||
isImageRemoved = true;
|
isImageRemoved = true;
|
||||||
ivProductImage.setImageResource(R.drawable.placeholder2);
|
binding.ivProductImage.setImageResource(R.drawable.placeholder2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -98,32 +94,22 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_product_detail, container, false);
|
binding = FragmentProductDetailBinding.inflate(inflater, container, false);
|
||||||
initViews(view);
|
|
||||||
loadCategories();
|
loadCategories();
|
||||||
handleArguments();
|
handleArguments();
|
||||||
|
|
||||||
btnBack.setOnClickListener(v -> navigateBack());
|
binding.btnProductBack.setOnClickListener(v -> navigateBack());
|
||||||
btnSave.setOnClickListener(v -> saveProduct());
|
binding.btnSaveProduct.setOnClickListener(v -> saveProduct());
|
||||||
btnDelete.setOnClickListener(v -> confirmDelete());
|
binding.btnDeleteProduct.setOnClickListener(v -> confirmDelete());
|
||||||
ivProductImage.setOnClickListener(v -> imagePickerHelper.showImagePickerDialog("Select Product Image", hasImage));
|
binding.ivProductImage.setOnClickListener(v -> imagePickerHelper.showImagePickerDialog("Select Product Image", hasImage));
|
||||||
return view;
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* get the UI components from the layout.
|
public void onDestroyView() {
|
||||||
*/
|
super.onDestroyView();
|
||||||
private void initViews(View v) {
|
binding = null;
|
||||||
tvMode = v.findViewById(R.id.tvProductMode);
|
|
||||||
tvProductId = v.findViewById(R.id.tvProductId);
|
|
||||||
etProductName = v.findViewById(R.id.etProductName);
|
|
||||||
etProductDesc = v.findViewById(R.id.etProductDesc);
|
|
||||||
etProductPrice = v.findViewById(R.id.etProductPrice);
|
|
||||||
spinnerCategory = v.findViewById(R.id.spinnerProductCategory);
|
|
||||||
btnSave = v.findViewById(R.id.btnSaveProduct);
|
|
||||||
btnDelete = v.findViewById(R.id.btnDeleteProduct);
|
|
||||||
btnBack = v.findViewById(R.id.btnProductBack);
|
|
||||||
ivProductImage = v.findViewById(R.id.ivProductImage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,7 +119,7 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
viewModel.getAllCategories(0, 100).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.getAllCategories(0, 100).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status == com.example.petstoremobile.utils.Resource.Status.SUCCESS && resource.data != null) {
|
if (resource != null && resource.status == com.example.petstoremobile.utils.Resource.Status.SUCCESS && resource.data != null) {
|
||||||
categoryList = resource.data.getContent();
|
categoryList = resource.data.getContent();
|
||||||
SpinnerUtils.populateSpinner(requireContext(), spinnerCategory, categoryList,
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerProductCategory, categoryList,
|
||||||
CategoryDTO::getCategoryName, "-- Select Category --",
|
CategoryDTO::getCategoryName, "-- Select Category --",
|
||||||
preselectedCategoryId, CategoryDTO::getCategoryId);
|
preselectedCategoryId, CategoryDTO::getCategoryId);
|
||||||
}
|
}
|
||||||
@@ -151,18 +137,18 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
preselectedCategoryId = a.getLong("categoryId", -1);
|
preselectedCategoryId = a.getLong("categoryId", -1);
|
||||||
hasImage = true;
|
hasImage = true;
|
||||||
|
|
||||||
tvMode.setText("Edit Product");
|
binding.tvProductMode.setText("Edit Product");
|
||||||
tvProductId.setText("ID: " + prodId);
|
binding.tvProductId.setText("ID: " + prodId);
|
||||||
tvProductId.setVisibility(View.VISIBLE);
|
binding.tvProductId.setVisibility(View.VISIBLE);
|
||||||
etProductName.setText(a.getString("prodName"));
|
binding.etProductName.setText(a.getString("prodName"));
|
||||||
etProductDesc.setText(a.getString("prodDesc"));
|
binding.etProductDesc.setText(a.getString("prodDesc"));
|
||||||
etProductPrice.setText(a.getString("prodPrice"));
|
binding.etProductPrice.setText(a.getString("prodPrice"));
|
||||||
btnDelete.setVisibility(View.VISIBLE);
|
binding.btnDeleteProduct.setVisibility(View.VISIBLE);
|
||||||
loadProductImage();
|
loadProductImage();
|
||||||
} else {
|
} else {
|
||||||
tvMode.setText("Add Product");
|
binding.tvProductMode.setText("Add Product");
|
||||||
btnDelete.setVisibility(View.GONE);
|
binding.btnDeleteProduct.setVisibility(View.GONE);
|
||||||
tvProductId.setVisibility(View.GONE);
|
binding.tvProductId.setVisibility(View.GONE);
|
||||||
hasImage = false;
|
hasImage = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,7 +160,7 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
String imageUrl = baseUrl + String.format(Locale.US, ProductApi.PRODUCT_IMAGE_PATH, prodId);
|
String imageUrl = baseUrl + String.format(Locale.US, ProductApi.PRODUCT_IMAGE_PATH, prodId);
|
||||||
String token = tokenManager.getToken();
|
String token = tokenManager.getToken();
|
||||||
|
|
||||||
GlideUtils.loadImageWithToken(requireContext(), ivProductImage, imageUrl, token, R.drawable.placeholder2, new GlideUtils.ImageLoadListener() {
|
GlideUtils.loadImageWithToken(requireContext(), binding.ivProductImage, imageUrl, token, R.drawable.placeholder2, new GlideUtils.ImageLoadListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onResourceReady() {
|
public void onResourceReady() {
|
||||||
hasImage = true;
|
hasImage = true;
|
||||||
@@ -240,22 +226,22 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
* Validates input fields and saves product information to the backend.
|
* Validates input fields and saves product information to the backend.
|
||||||
*/
|
*/
|
||||||
private void saveProduct() {
|
private void saveProduct() {
|
||||||
if (!InputValidator.isNotEmpty(etProductName, "Product Name")) return;
|
if (!InputValidator.isNotEmpty(binding.etProductName, "Product Name")) return;
|
||||||
|
|
||||||
if (spinnerCategory.getSelectedItemPosition() == 0) {
|
if (binding.spinnerProductCategory.getSelectedItemPosition() == 0) {
|
||||||
Toast.makeText(getContext(), "Select a category", Toast.LENGTH_SHORT).show(); return;
|
Toast.makeText(getContext(), "Select a category", Toast.LENGTH_SHORT).show(); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InputValidator.isNotEmpty(etProductPrice, "Price") ||
|
if (!InputValidator.isNotEmpty(binding.etProductPrice, "Price") ||
|
||||||
!InputValidator.isPositiveDecimal(etProductPrice, "Price")) {
|
!InputValidator.isPositiveDecimal(binding.etProductPrice, "Price")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = etProductName.getText().toString().trim();
|
String name = binding.etProductName.getText().toString().trim();
|
||||||
String desc = etProductDesc.getText().toString().trim();
|
String desc = binding.etProductDesc.getText().toString().trim();
|
||||||
BigDecimal price = new BigDecimal(etProductPrice.getText().toString().trim());
|
BigDecimal price = new BigDecimal(binding.etProductPrice.getText().toString().trim());
|
||||||
|
|
||||||
CategoryDTO category = categoryList.get(spinnerCategory.getSelectedItemPosition() - 1);
|
CategoryDTO category = categoryList.get(binding.spinnerProductCategory.getSelectedItemPosition() - 1);
|
||||||
ProductDTO dto = new ProductDTO(name, category.getCategoryId(), desc, price);
|
ProductDTO dto = new ProductDTO(name, category.getCategoryId(), desc, price);
|
||||||
|
|
||||||
if (isEditing) {
|
if (isEditing) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.databinding.FragmentProductSupplierDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.*;
|
import com.example.petstoremobile.dtos.*;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
import com.example.petstoremobile.utils.InputValidator;
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
@@ -29,10 +29,7 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class ProductSupplierDetailFragment extends Fragment {
|
public class ProductSupplierDetailFragment extends Fragment {
|
||||||
|
|
||||||
private TextView tvMode;
|
private FragmentProductSupplierDetailBinding binding;
|
||||||
private Spinner spinnerProduct, spinnerSupplier;
|
|
||||||
private EditText etCost;
|
|
||||||
private Button btnSave, btnDelete, btnBack;
|
|
||||||
|
|
||||||
private boolean isEditing = false;
|
private boolean isEditing = false;
|
||||||
private long editProductId = -1;
|
private long editProductId = -1;
|
||||||
@@ -58,28 +55,20 @@ public class ProductSupplierDetailFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_product_supplier_detail, container, false);
|
binding = FragmentProductSupplierDetailBinding.inflate(inflater, container, false);
|
||||||
initViews(view);
|
|
||||||
loadData();
|
loadData();
|
||||||
handleArguments();
|
handleArguments();
|
||||||
|
|
||||||
btnBack.setOnClickListener(v -> navigateBack());
|
binding.btnPSBack.setOnClickListener(v -> navigateBack());
|
||||||
btnSave.setOnClickListener(v -> save());
|
binding.btnSavePS.setOnClickListener(v -> save());
|
||||||
btnDelete.setOnClickListener(v -> confirmDelete());
|
binding.btnDeletePS.setOnClickListener(v -> confirmDelete());
|
||||||
return view;
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Initializes UI components from the layout.
|
public void onDestroyView() {
|
||||||
*/
|
super.onDestroyView();
|
||||||
private void initViews(View v) {
|
binding = null;
|
||||||
tvMode = v.findViewById(R.id.tvPSMode);
|
|
||||||
spinnerProduct = v.findViewById(R.id.spinnerPSProduct);
|
|
||||||
spinnerSupplier = v.findViewById(R.id.spinnerPSSupplier);
|
|
||||||
etCost = v.findViewById(R.id.etPSCost);
|
|
||||||
btnSave = v.findViewById(R.id.btnSavePS);
|
|
||||||
btnDelete = v.findViewById(R.id.btnDeletePS);
|
|
||||||
btnBack = v.findViewById(R.id.btnPSBack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,7 +86,7 @@ public class ProductSupplierDetailFragment extends Fragment {
|
|||||||
productViewModel.getAllProducts(null, 0, 200).observe(getViewLifecycleOwner(), resource -> {
|
productViewModel.getAllProducts(null, 0, 200).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
productList = resource.data.getContent();
|
productList = resource.data.getContent();
|
||||||
SpinnerUtils.populateSpinner(requireContext(), spinnerProduct, productList,
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerPSProduct, productList,
|
||||||
ProductDTO::getProdName, "-- Select Product --",
|
ProductDTO::getProdName, "-- Select Product --",
|
||||||
preselectedProductId, ProductDTO::getProdId);
|
preselectedProductId, ProductDTO::getProdId);
|
||||||
}
|
}
|
||||||
@@ -111,7 +100,7 @@ public class ProductSupplierDetailFragment extends Fragment {
|
|||||||
supplierViewModel.getAllSuppliers(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
supplierViewModel.getAllSuppliers(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
supplierList = resource.data.getContent();
|
supplierList = resource.data.getContent();
|
||||||
SpinnerUtils.populateSpinner(requireContext(), spinnerSupplier, supplierList,
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerPSSupplier, supplierList,
|
||||||
SupplierDTO::getSupCompany, "-- Select Supplier --",
|
SupplierDTO::getSupCompany, "-- Select Supplier --",
|
||||||
preselectedSupplierId, SupplierDTO::getSupId);
|
preselectedSupplierId, SupplierDTO::getSupId);
|
||||||
}
|
}
|
||||||
@@ -129,12 +118,12 @@ public class ProductSupplierDetailFragment extends Fragment {
|
|||||||
editSupplierId = a.getLong("supplierId");
|
editSupplierId = a.getLong("supplierId");
|
||||||
preselectedProductId = editProductId;
|
preselectedProductId = editProductId;
|
||||||
preselectedSupplierId = editSupplierId;
|
preselectedSupplierId = editSupplierId;
|
||||||
etCost.setText(a.getString("cost"));
|
binding.etPSCost.setText(a.getString("cost"));
|
||||||
tvMode.setText("Edit Product Supplier");
|
binding.tvPSMode.setText("Edit Product Supplier");
|
||||||
btnDelete.setVisibility(View.VISIBLE);
|
binding.btnDeletePS.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
tvMode.setText("Add Product Supplier");
|
binding.tvPSMode.setText("Add Product Supplier");
|
||||||
btnDelete.setVisibility(View.GONE);
|
binding.btnDeletePS.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,21 +131,21 @@ public class ProductSupplierDetailFragment extends Fragment {
|
|||||||
* Validates input and saves the product-supplier to the backend.
|
* Validates input and saves the product-supplier to the backend.
|
||||||
*/
|
*/
|
||||||
private void save() {
|
private void save() {
|
||||||
if (spinnerProduct.getSelectedItemPosition() == 0) {
|
if (binding.spinnerPSProduct.getSelectedItemPosition() == 0) {
|
||||||
Toast.makeText(getContext(), "Select a product", Toast.LENGTH_SHORT).show(); return;
|
Toast.makeText(getContext(), "Select a product", Toast.LENGTH_SHORT).show(); return;
|
||||||
}
|
}
|
||||||
if (spinnerSupplier.getSelectedItemPosition() == 0) {
|
if (binding.spinnerPSSupplier.getSelectedItemPosition() == 0) {
|
||||||
Toast.makeText(getContext(), "Select a supplier", Toast.LENGTH_SHORT).show(); return;
|
Toast.makeText(getContext(), "Select a supplier", Toast.LENGTH_SHORT).show(); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InputValidator.isNotEmpty(etCost, "Cost") ||
|
if (!InputValidator.isNotEmpty(binding.etPSCost, "Cost") ||
|
||||||
!InputValidator.isPositiveDecimal(etCost, "Cost")) {
|
!InputValidator.isPositiveDecimal(binding.etPSCost, "Cost")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProductDTO product = productList.get(spinnerProduct.getSelectedItemPosition() - 1);
|
ProductDTO product = productList.get(binding.spinnerPSProduct.getSelectedItemPosition() - 1);
|
||||||
SupplierDTO supplier = supplierList.get(spinnerSupplier.getSelectedItemPosition() - 1);
|
SupplierDTO supplier = supplierList.get(binding.spinnerPSSupplier.getSelectedItemPosition() - 1);
|
||||||
BigDecimal cost = new BigDecimal(etCost.getText().toString().trim());
|
BigDecimal cost = new BigDecimal(binding.etPSCost.getText().toString().trim());
|
||||||
|
|
||||||
ProductSupplierDTO dto = new ProductSupplierDTO(
|
ProductSupplierDTO dto = new ProductSupplierDTO(
|
||||||
product.getProdId(), supplier.getSupId(), cost);
|
product.getProdId(), supplier.getSupId(), cost);
|
||||||
|
|||||||
@@ -3,12 +3,11 @@ package com.example.petstoremobile.fragments.listfragments.detailfragments;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
import android.widget.*;
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.databinding.FragmentPurchaseOrderDetailBinding;
|
||||||
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
|
|
||||||
@@ -18,8 +17,7 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class PurchaseOrderDetailFragment extends Fragment {
|
public class PurchaseOrderDetailFragment extends Fragment {
|
||||||
|
|
||||||
private TextView tvId, tvSupplier, tvDate, tvStatus;
|
private FragmentPurchaseOrderDetailBinding binding;
|
||||||
private Button btnBack;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inflates the layout, initializes views, and populates order data from arguments.
|
* Inflates the layout, initializes views, and populates order data from arguments.
|
||||||
@@ -27,38 +25,38 @@ public class PurchaseOrderDetailFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_purchase_order_detail, container, false);
|
binding = FragmentPurchaseOrderDetailBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
tvId = view.findViewById(R.id.tvPODetailId);
|
|
||||||
tvSupplier = view.findViewById(R.id.tvPODetailSupplier);
|
|
||||||
tvDate = view.findViewById(R.id.tvPODetailDate);
|
|
||||||
tvStatus = view.findViewById(R.id.tvPODetailStatus);
|
|
||||||
btnBack = view.findViewById(R.id.btnPOBack);
|
|
||||||
|
|
||||||
Bundle a = getArguments();
|
Bundle a = getArguments();
|
||||||
if (a != null) {
|
if (a != null) {
|
||||||
tvId.setText("PO #" + a.getLong("purchaseOrderId"));
|
binding.tvPODetailId.setText("PO #" + a.getLong("purchaseOrderId"));
|
||||||
tvSupplier.setText(a.getString("supplierName"));
|
binding.tvPODetailSupplier.setText(a.getString("supplierName"));
|
||||||
tvDate.setText(a.getString("orderDate"));
|
binding.tvPODetailDate.setText(a.getString("orderDate"));
|
||||||
|
|
||||||
String status = a.getString("status", "");
|
String status = a.getString("status", "");
|
||||||
tvStatus.setText(status);
|
binding.tvPODetailStatus.setText(status);
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "Completed":
|
case "Completed":
|
||||||
tvStatus.setTextColor(Color.parseColor("#4CAF50")); break;
|
binding.tvPODetailStatus.setTextColor(Color.parseColor("#4CAF50")); break;
|
||||||
case "Pending":
|
case "Pending":
|
||||||
tvStatus.setTextColor(Color.parseColor("#FF9800")); break;
|
binding.tvPODetailStatus.setTextColor(Color.parseColor("#FF9800")); break;
|
||||||
case "Cancelled":
|
case "Cancelled":
|
||||||
tvStatus.setTextColor(Color.parseColor("#F44336")); break;
|
binding.tvPODetailStatus.setTextColor(Color.parseColor("#F44336")); break;
|
||||||
default:
|
default:
|
||||||
tvStatus.setTextColor(Color.parseColor("#9E9E9E")); break;
|
binding.tvPODetailStatus.setTextColor(Color.parseColor("#9E9E9E")); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btnBack.setOnClickListener(v -> {
|
binding.btnPOBack.setOnClickListener(v -> {
|
||||||
NavHostFragment.findNavController(this).popBackStack();
|
NavHostFragment.findNavController(this).popBackStack();
|
||||||
});
|
});
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,17 @@
|
|||||||
package com.example.petstoremobile.fragments.listfragments.detailfragments;
|
package com.example.petstoremobile.fragments.listfragments.detailfragments;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
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 android.widget.Toast;
|
||||||
import com.example.petstoremobile.R;
|
|
||||||
import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
|
|
||||||
import com.example.petstoremobile.api.SaleApi;
|
import com.example.petstoremobile.api.SaleApi;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentRefundDetailBinding;
|
||||||
import com.example.petstoremobile.fragments.listfragments.SaleFragment;
|
import com.example.petstoremobile.fragments.listfragments.SaleFragment;
|
||||||
import com.example.petstoremobile.utils.ActivityLogger;
|
import com.example.petstoremobile.utils.ActivityLogger;
|
||||||
import com.example.petstoremobile.utils.InputValidator;
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
@@ -28,10 +24,7 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class RefundDetailFragment extends Fragment {
|
public class RefundDetailFragment extends Fragment {
|
||||||
|
|
||||||
private EditText etRefundSaleId, etRefundReason;
|
private FragmentRefundDetailBinding binding;
|
||||||
private TextView tvSaleInfo;
|
|
||||||
private Spinner spinnerRefundPayment;
|
|
||||||
private Button btnLoadSale, btnProcessRefund, btnBack;
|
|
||||||
private int saleId;
|
private int saleId;
|
||||||
private SaleFragment saleFragment;
|
private SaleFragment saleFragment;
|
||||||
|
|
||||||
@@ -42,23 +35,28 @@ public class RefundDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_refund_detail, container, false);
|
binding = FragmentRefundDetailBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
initViews(view);
|
|
||||||
setupSpinner();
|
setupSpinner();
|
||||||
handleArguments();
|
handleArguments();
|
||||||
|
|
||||||
btnBack.setOnClickListener(v -> goBack());
|
binding.btnRefundBack.setOnClickListener(v -> goBack());
|
||||||
btnLoadSale.setOnClickListener(v -> loadSaleDetails());
|
binding.btnLoadSale.setOnClickListener(v -> loadSaleDetails());
|
||||||
btnProcessRefund.setOnClickListener(v -> processRefund());
|
binding.btnProcessRefund.setOnClickListener(v -> processRefund());
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadSaleDetails() {
|
private void loadSaleDetails() {
|
||||||
String idText = etRefundSaleId.getText().toString().trim();
|
String idText = binding.etRefundSaleId.getText().toString().trim();
|
||||||
if (idText.isEmpty()) {
|
if (idText.isEmpty()) {
|
||||||
Toast.makeText(getContext(), "Enter a Sale ID", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Enter a Sale ID", Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
@@ -68,22 +66,21 @@ public class RefundDetailFragment extends Fragment {
|
|||||||
int id = Integer.parseInt(idText);
|
int id = Integer.parseInt(idText);
|
||||||
// TODO: Replace with actual API call - GET v1/sales/{id}
|
// TODO: Replace with actual API call - GET v1/sales/{id}
|
||||||
// For now show placeholder info
|
// For now show placeholder info
|
||||||
tvSaleInfo.setText("Sale ID: " + id + " loaded. Enter reason and payment method to process refund.");
|
binding.tvSaleInfo.setText("Sale ID: " + id + " loaded. Enter reason and payment method to process refund.");
|
||||||
tvSaleInfo.setTextColor(getResources().getColor(android.R.color.holo_green_dark));
|
binding.tvSaleInfo.setTextColor(getResources().getColor(android.R.color.holo_green_dark));
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
Toast.makeText(getContext(), "Invalid Sale ID", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Invalid Sale ID", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processRefund() {
|
private void processRefund() {
|
||||||
if (!InputValidator.isNotEmpty(etRefundSaleId, "Sale ID"))
|
if (!InputValidator.isNotEmpty(binding.etRefundSaleId, "Sale ID"))
|
||||||
return;
|
return;
|
||||||
if (!InputValidator.isNotEmpty(etRefundReason, "Refund Reason"))
|
if (!InputValidator.isNotEmpty(binding.etRefundReason, "Refund Reason"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
String idText = etRefundSaleId.getText().toString().trim();
|
String idText = binding.etRefundSaleId.getText().toString().trim();
|
||||||
String reason = etRefundReason.getText().toString().trim();
|
String reason = binding.etRefundReason.getText().toString().trim();
|
||||||
String payment = spinnerRefundPayment.getSelectedItem().toString();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int id = Integer.parseInt(idText);
|
int id = Integer.parseInt(idText);
|
||||||
@@ -101,16 +98,16 @@ public class RefundDetailFragment extends Fragment {
|
|||||||
private void handleArguments() {
|
private void handleArguments() {
|
||||||
if (getArguments() != null && getArguments().containsKey("saleId")) {
|
if (getArguments() != null && getArguments().containsKey("saleId")) {
|
||||||
saleId = getArguments().getInt("saleId");
|
saleId = getArguments().getInt("saleId");
|
||||||
etRefundSaleId.setText(String.valueOf(saleId));
|
binding.etRefundSaleId.setText(String.valueOf(saleId));
|
||||||
String info = "Sale Date: " + getArguments().getString("saleDate")
|
String info = "Sale Date: " + getArguments().getString("saleDate")
|
||||||
+ " | Employee: " + getArguments().getString("employeeName")
|
+ " | Employee: " + getArguments().getString("employeeName")
|
||||||
+ " | Total: $" + String.format("%.2f", getArguments().getDouble("total"))
|
+ " | Total: $" + String.format("%.2f", getArguments().getDouble("total"))
|
||||||
+ " | Payment: " + getArguments().getString("paymentMethod");
|
+ " | Payment: " + getArguments().getString("paymentMethod");
|
||||||
tvSaleInfo.setText(info);
|
binding.tvSaleInfo.setText(info);
|
||||||
tvSaleInfo.setTextColor(getResources().getColor(android.R.color.holo_green_dark));
|
binding.tvSaleInfo.setTextColor(getResources().getColor(android.R.color.holo_green_dark));
|
||||||
|
|
||||||
// Pre-select payment method
|
// Pre-select payment method
|
||||||
SpinnerUtils.setSelectionByValue(spinnerRefundPayment, getArguments().getString("paymentMethod"));
|
SpinnerUtils.setSelectionByValue(binding.spinnerRefundPayment, getArguments().getString("paymentMethod"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,18 +115,8 @@ public class RefundDetailFragment extends Fragment {
|
|||||||
NavHostFragment.findNavController(this).popBackStack();
|
NavHostFragment.findNavController(this).popBackStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initViews(View view) {
|
|
||||||
etRefundSaleId = view.findViewById(R.id.etRefundSaleId);
|
|
||||||
etRefundReason = view.findViewById(R.id.etRefundReason);
|
|
||||||
tvSaleInfo = view.findViewById(R.id.tvSaleInfo);
|
|
||||||
spinnerRefundPayment = view.findViewById(R.id.spinnerRefundPayment);
|
|
||||||
btnLoadSale = view.findViewById(R.id.btnLoadSale);
|
|
||||||
btnProcessRefund = view.findViewById(R.id.btnProcessRefund);
|
|
||||||
btnBack = view.findViewById(R.id.btnRefundBack);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupSpinner() {
|
private void setupSpinner() {
|
||||||
SpinnerUtils.setupStringSpinner(requireContext(), spinnerRefundPayment,
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerRefundPayment,
|
||||||
new String[] { "Cash", "Card", "Debit" });
|
new String[] { "Cash", "Card", "Debit" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,10 @@ import androidx.navigation.fragment.NavHostFragment;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
|
import com.example.petstoremobile.databinding.FragmentServiceDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.ServiceDTO;
|
import com.example.petstoremobile.dtos.ServiceDTO;
|
||||||
import com.example.petstoremobile.utils.ActivityLogger;
|
import com.example.petstoremobile.utils.ActivityLogger;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
@@ -31,9 +29,7 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class ServiceDetailFragment extends Fragment {
|
public class ServiceDetailFragment extends Fragment {
|
||||||
|
|
||||||
private TextView tvMode, tvServiceId;
|
private FragmentServiceDetailBinding binding;
|
||||||
private EditText etServiceName, etServiceDesc, etServiceDuration, etServicePrice;
|
|
||||||
private Button btnSaveService, btnDeleteService, btnBack;
|
|
||||||
private int serviceId;
|
private int serviceId;
|
||||||
private boolean isEditing = false;
|
private boolean isEditing = false;
|
||||||
|
|
||||||
@@ -48,18 +44,23 @@ public class ServiceDetailFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_service_detail, container, false);
|
binding = FragmentServiceDetailBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
//get controls from layout and display the view depending on the mode
|
//get controls from layout and display the view depending on the mode
|
||||||
initViews(view);
|
|
||||||
handleArguments();
|
handleArguments();
|
||||||
|
|
||||||
//set button click listeners
|
//set button click listeners
|
||||||
btnBack.setOnClickListener(v -> navigateBack());
|
binding.btnBack.setOnClickListener(v -> navigateBack());
|
||||||
btnSaveService.setOnClickListener(v -> saveService());
|
binding.btnSaveService.setOnClickListener(v -> saveService());
|
||||||
btnDeleteService.setOnClickListener(v -> deleteService());
|
binding.btnDeleteService.setOnClickListener(v -> deleteService());
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,16 +68,16 @@ public class ServiceDetailFragment extends Fragment {
|
|||||||
*/
|
*/
|
||||||
private void saveService() {
|
private void saveService() {
|
||||||
// Validates all fields using InputValidator
|
// Validates all fields using InputValidator
|
||||||
if (!InputValidator.isNotEmpty(etServiceName, "Service Name")) return;
|
if (!InputValidator.isNotEmpty(binding.etServiceName, "Service Name")) return;
|
||||||
if (!InputValidator.isNotEmpty(etServiceDesc, "Description")) return;
|
if (!InputValidator.isNotEmpty(binding.etServiceDesc, "Description")) return;
|
||||||
if (!InputValidator.isPositiveInteger(etServiceDuration, "Duration")) return;
|
if (!InputValidator.isPositiveInteger(binding.etServiceDuration, "Duration")) return;
|
||||||
if (!InputValidator.isPositiveDecimal(etServicePrice, "Price")) return;
|
if (!InputValidator.isPositiveDecimal(binding.etServicePrice, "Price")) return;
|
||||||
|
|
||||||
//get all the values from the fields
|
//get all the values from the fields
|
||||||
String name = etServiceName.getText().toString().trim();
|
String name = binding.etServiceName.getText().toString().trim();
|
||||||
String desc = etServiceDesc.getText().toString().trim();
|
String desc = binding.etServiceDesc.getText().toString().trim();
|
||||||
int duration = Integer.parseInt(etServiceDuration.getText().toString().trim());
|
int duration = Integer.parseInt(binding.etServiceDuration.getText().toString().trim());
|
||||||
double price = Double.parseDouble(etServicePrice.getText().toString().trim());
|
double price = Double.parseDouble(binding.etServicePrice.getText().toString().trim());
|
||||||
|
|
||||||
//create a service object to send to the API
|
//create a service object to send to the API
|
||||||
ServiceDTO serviceDTO = new ServiceDTO();
|
ServiceDTO serviceDTO = new ServiceDTO();
|
||||||
@@ -143,36 +144,21 @@ public class ServiceDetailFragment extends Fragment {
|
|||||||
// Get service data from arguments and populate fields
|
// Get service data from arguments and populate fields
|
||||||
isEditing = true;
|
isEditing = true;
|
||||||
serviceId = getArguments().getInt("serviceId");
|
serviceId = getArguments().getInt("serviceId");
|
||||||
tvMode.setText("Edit Service");
|
binding.tvMode.setText("Edit Service");
|
||||||
tvServiceId.setText("ID: " + serviceId);
|
binding.tvServiceId.setText("ID: " + serviceId);
|
||||||
etServiceName.setText(getArguments().getString("serviceName"));
|
binding.etServiceName.setText(getArguments().getString("serviceName"));
|
||||||
etServiceDesc.setText(getArguments().getString("serviceDesc"));
|
binding.etServiceDesc.setText(getArguments().getString("serviceDesc"));
|
||||||
etServiceDuration.setText(String.valueOf(getArguments().getInt("serviceDuration")));
|
binding.etServiceDuration.setText(String.valueOf(getArguments().getInt("serviceDuration")));
|
||||||
etServicePrice.setText(String.valueOf(getArguments().getDouble("servicePrice")));
|
binding.etServicePrice.setText(String.valueOf(getArguments().getDouble("servicePrice")));
|
||||||
btnDeleteService.setVisibility(View.VISIBLE);
|
binding.btnDeleteService.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
// Service is being added
|
// Service is being added
|
||||||
// Set default values for add a new service
|
// Set default values for add a new service
|
||||||
isEditing = false;
|
isEditing = false;
|
||||||
tvMode.setText("Add Service");
|
binding.tvMode.setText("Add Service");
|
||||||
tvServiceId.setVisibility(View.GONE);
|
binding.tvServiceId.setVisibility(View.GONE);
|
||||||
btnDeleteService.setVisibility(View.GONE);
|
binding.btnDeleteService.setVisibility(View.GONE);
|
||||||
btnSaveService.setText("Add");
|
binding.btnSaveService.setText("Add");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes UI components from the layout.
|
|
||||||
*/
|
|
||||||
private void initViews(View view) {
|
|
||||||
tvMode = view.findViewById(R.id.tvMode);
|
|
||||||
tvServiceId = view.findViewById(R.id.tvServiceId);
|
|
||||||
etServiceName = view.findViewById(R.id.etServiceName);
|
|
||||||
etServiceDesc = view.findViewById(R.id.etServiceDesc);
|
|
||||||
etServiceDuration = view.findViewById(R.id.etServiceDuration);
|
|
||||||
etServicePrice = view.findViewById(R.id.etServicePrice);
|
|
||||||
btnSaveService = view.findViewById(R.id.btnSaveService);
|
|
||||||
btnDeleteService = view.findViewById(R.id.btnDeleteService);
|
|
||||||
btnBack = view.findViewById(R.id.btnBack);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,9 @@ import androidx.navigation.fragment.NavHostFragment;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.databinding.FragmentSupplierDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.SupplierDTO;
|
import com.example.petstoremobile.dtos.SupplierDTO;
|
||||||
import com.example.petstoremobile.utils.ActivityLogger;
|
import com.example.petstoremobile.utils.ActivityLogger;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
@@ -32,9 +29,7 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class SupplierDetailFragment extends Fragment {
|
public class SupplierDetailFragment extends Fragment {
|
||||||
|
|
||||||
private TextView tvMode, tvSupId;
|
private FragmentSupplierDetailBinding binding;
|
||||||
private EditText etSupCompany, etSupContactFirstName, etSupContactLastName, etSupEmail, etSupPhone;
|
|
||||||
private Button btnSaveSupplier, btnDeleteSupplier, btnBack;
|
|
||||||
private int supId;
|
private int supId;
|
||||||
private boolean isEditing = false;
|
private boolean isEditing = false;
|
||||||
|
|
||||||
@@ -49,18 +44,25 @@ public class SupplierDetailFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_supplier_detail, container, false);
|
binding = FragmentSupplierDetailBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
|
// Add phone number formatting (CA) and limit length to 14 characters
|
||||||
|
UIUtils.formatPhoneInput(binding.etSupPhone);
|
||||||
|
|
||||||
//get controls from layout and display the view depending on the mode
|
|
||||||
initViews(view);
|
|
||||||
handleArguments();
|
handleArguments();
|
||||||
|
|
||||||
//set button click listeners
|
//set button click listeners
|
||||||
btnBack.setOnClickListener(v -> navigateBack());
|
binding.btnBack.setOnClickListener(v -> navigateBack());
|
||||||
btnSaveSupplier.setOnClickListener(v -> saveSupplier());
|
binding.btnSaveSupplier.setOnClickListener(v -> saveSupplier());
|
||||||
btnDeleteSupplier.setOnClickListener(v -> deleteSupplier());
|
binding.btnDeleteSupplier.setOnClickListener(v -> deleteSupplier());
|
||||||
|
|
||||||
return view;
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,18 +70,18 @@ public class SupplierDetailFragment extends Fragment {
|
|||||||
*/
|
*/
|
||||||
private void saveSupplier() {
|
private void saveSupplier() {
|
||||||
// Validates all fields using InputValidator
|
// Validates all fields using InputValidator
|
||||||
if (!InputValidator.isNotEmpty(etSupCompany, "Company Name")) return;
|
if (!InputValidator.isNotEmpty(binding.etSupCompany, "Company Name")) return;
|
||||||
if (!InputValidator.isNotEmpty(etSupContactFirstName, "First Name")) return;
|
if (!InputValidator.isNotEmpty(binding.etSupContactFirstName, "First Name")) return;
|
||||||
if (!InputValidator.isNotEmpty(etSupContactLastName, "Last Name")) return;
|
if (!InputValidator.isNotEmpty(binding.etSupContactLastName, "Last Name")) return;
|
||||||
if (!InputValidator.isValidEmail(etSupEmail)) return;
|
if (!InputValidator.isValidEmail(binding.etSupEmail)) return;
|
||||||
if (!InputValidator.isValidPhone(etSupPhone)) return;
|
if (!InputValidator.isValidPhone(binding.etSupPhone)) return;
|
||||||
|
|
||||||
//get all the values from the fields
|
//get all the values from the fields
|
||||||
String company = etSupCompany.getText().toString().trim();
|
String company = binding.etSupCompany.getText().toString().trim();
|
||||||
String firstName = etSupContactFirstName.getText().toString().trim();
|
String firstName = binding.etSupContactFirstName.getText().toString().trim();
|
||||||
String lastName = etSupContactLastName.getText().toString().trim();
|
String lastName = binding.etSupContactLastName.getText().toString().trim();
|
||||||
String email = etSupEmail.getText().toString().trim();
|
String email = binding.etSupEmail.getText().toString().trim();
|
||||||
String phone = etSupPhone.getText().toString().trim();
|
String phone = binding.etSupPhone.getText().toString().trim();
|
||||||
|
|
||||||
//create a supplier object to send to the API
|
//create a supplier object to send to the API
|
||||||
SupplierDTO supplierDTO = new SupplierDTO();
|
SupplierDTO supplierDTO = new SupplierDTO();
|
||||||
@@ -148,42 +150,22 @@ public class SupplierDetailFragment extends Fragment {
|
|||||||
// Get supplier data from arguments and populate fields
|
// Get supplier data from arguments and populate fields
|
||||||
isEditing = true;
|
isEditing = true;
|
||||||
supId = getArguments().getInt("supId");
|
supId = getArguments().getInt("supId");
|
||||||
tvMode.setText("Edit Supplier");
|
binding.tvMode.setText("Edit Supplier");
|
||||||
tvSupId.setText("ID: " + supId);
|
binding.tvSupId.setText("ID: " + supId);
|
||||||
etSupCompany.setText(getArguments().getString("supCompany"));
|
binding.etSupCompany.setText(getArguments().getString("supCompany"));
|
||||||
etSupContactFirstName.setText(getArguments().getString("supContactFirstName"));
|
binding.etSupContactFirstName.setText(getArguments().getString("supContactFirstName"));
|
||||||
etSupContactLastName.setText(getArguments().getString("supContactLastName"));
|
binding.etSupContactLastName.setText(getArguments().getString("supContactLastName"));
|
||||||
etSupEmail.setText(getArguments().getString("supEmail"));
|
binding.etSupEmail.setText(getArguments().getString("supEmail"));
|
||||||
etSupPhone.setText(getArguments().getString("supPhone"));
|
binding.etSupPhone.setText(getArguments().getString("supPhone"));
|
||||||
btnDeleteSupplier.setVisibility(View.VISIBLE);
|
binding.btnDeleteSupplier.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
// Supplier is being added
|
// Supplier is being added
|
||||||
// Set default values for add a new supplier
|
// Set default values for add a new supplier
|
||||||
isEditing = false;
|
isEditing = false;
|
||||||
tvMode.setText("Add Supplier");
|
binding.tvMode.setText("Add Supplier");
|
||||||
tvSupId.setVisibility(View.GONE);
|
binding.tvSupId.setVisibility(View.GONE);
|
||||||
btnDeleteSupplier.setVisibility(View.GONE);
|
binding.btnDeleteSupplier.setVisibility(View.GONE);
|
||||||
btnSaveSupplier.setText("Add");
|
binding.btnSaveSupplier.setText("Add");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the UI components and sets up formatting for phone input.
|
|
||||||
*/
|
|
||||||
private void initViews(View view) {
|
|
||||||
tvMode = view.findViewById(R.id.tvMode);
|
|
||||||
tvSupId = view.findViewById(R.id.tvSupId);
|
|
||||||
etSupCompany = view.findViewById(R.id.etSupCompany);
|
|
||||||
etSupContactFirstName = view.findViewById(R.id.etSupContactFirstName);
|
|
||||||
etSupContactLastName = view.findViewById(R.id.etSupContactLastName);
|
|
||||||
etSupEmail = view.findViewById(R.id.etSupEmail);
|
|
||||||
etSupPhone = view.findViewById(R.id.etSupPhone);
|
|
||||||
|
|
||||||
// Add phone number formatting (CA) and limit length to 14 characters
|
|
||||||
UIUtils.formatPhoneInput(etSupPhone);
|
|
||||||
|
|
||||||
btnSaveSupplier = view.findViewById(R.id.btnSaveSupplier);
|
|
||||||
btnDeleteSupplier = view.findViewById(R.id.btnDeleteSupplier);
|
|
||||||
btnBack = view.findViewById(R.id.btnBack);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user