integrated hilt so we dont have to manually pass context and inject retrofit in andriod

This commit is contained in:
Alex
2026-04-04 18:15:05 -06:00
parent 4ea76ddab5
commit ddc8e98c19
37 changed files with 504 additions and 194 deletions

View File

@@ -2,6 +2,7 @@ import java.util.Properties
plugins { plugins {
alias(libs.plugins.android.application) alias(libs.plugins.android.application)
alias(libs.plugins.hilt)
} }
val localProperties = Properties().apply { val localProperties = Properties().apply {
@@ -60,6 +61,9 @@ dependencies {
implementation(libs.activity) implementation(libs.activity)
implementation(libs.constraintlayout) implementation(libs.constraintlayout)
implementation(libs.hilt.android)
annotationProcessor(libs.hilt.compiler)
implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")

View File

@@ -1,8 +1,9 @@
package com.example.petstoremobile; package com.example.petstoremobile;
import android.app.Application; import android.app.Application;
import com.example.petstoremobile.api.auth.TokenManager; import dagger.hilt.android.HiltAndroidApp;
@HiltAndroidApp
public class PetStoreApplication extends Application { public class PetStoreApplication extends Application {
@Override @Override
public void onCreate() { public void onCreate() {

View File

@@ -10,7 +10,6 @@ import android.util.Log;
import androidx.activity.EdgeToEdge; import androidx.activity.EdgeToEdge;
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.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.graphics.Insets; import androidx.core.graphics.Insets;
@@ -25,6 +24,9 @@ import com.example.petstoremobile.fragments.ProfileFragment;
import com.example.petstoremobile.services.ChatNotificationService; import com.example.petstoremobile.services.ChatNotificationService;
import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.bottomnavigation.BottomNavigationView;
import dagger.hilt.android.AndroidEntryPoint;
@AndroidEntryPoint
public class HomeActivity extends AppCompatActivity { public class HomeActivity extends AppCompatActivity {
private BottomNavigationView bottomNav; private BottomNavigationView bottomNav;
@@ -125,4 +127,4 @@ public class HomeActivity extends AppCompatActivity {
.replace(R.id.fragment_container, fragment) .replace(R.id.fragment_container, fragment)
.commit(); .commit();
} }
} }

View File

@@ -18,15 +18,19 @@ import androidx.core.view.WindowInsetsCompat;
import com.example.petstoremobile.R; import com.example.petstoremobile.R;
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.api.RetrofitClient;
import com.example.petstoremobile.dtos.AuthDTO; import com.example.petstoremobile.dtos.AuthDTO;
import com.example.petstoremobile.dtos.UserDTO; import com.example.petstoremobile.dtos.UserDTO;
import javax.inject.Inject;
import javax.inject.Named;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
//The login screen activity //The login screen activity
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
private EditText etUser; private EditText etUser;
@@ -34,6 +38,10 @@ public class MainActivity extends AppCompatActivity {
private Button btnLogin; private Button btnLogin;
private TextView tvLoginStatus; private TextView tvLoginStatus;
@Inject AuthApi authApi;
@Inject TokenManager tokenManager;
@Inject @Named("baseUrl") String baseUrl;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@@ -41,7 +49,6 @@ public class MainActivity extends AppCompatActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// Check if user is already logged in // Check if user is already logged in
TokenManager tokenManager = TokenManager.getInstance(this);
if (tokenManager.isLoggedIn()) { if (tokenManager.isLoggedIn()) {
if ("CUSTOMER".equalsIgnoreCase(tokenManager.getRole())) { if ("CUSTOMER".equalsIgnoreCase(tokenManager.getRole())) {
// If a customer somehow remained logged in, clear them out // If a customer somehow remained logged in, clear them out
@@ -92,8 +99,6 @@ public class MainActivity extends AppCompatActivity {
return; return;
} }
AuthApi authApi = RetrofitClient.getAuthApi(this);
//Call login from api and get response //Call login from api and get response
authApi.login(new AuthDTO.LoginRequest(username,password)).enqueue(new Callback<AuthDTO.LoginResponse>() { authApi.login(new AuthDTO.LoginRequest(username,password)).enqueue(new Callback<AuthDTO.LoginResponse>() {
@Override @Override
@@ -109,21 +114,20 @@ public class MainActivity extends AppCompatActivity {
} }
//save login data in shared preferences //save login data in shared preferences
TokenManager.getInstance(MainActivity.this).saveLoginData( tokenManager.saveLoginData(
response.body().getToken(), response.body().getToken(),
response.body().getUsername(), response.body().getUsername(),
role role
); );
//fetch user id from api then login to home activity //fetch user id from api then login to home activity
RetrofitClient.getAuthApi(MainActivity.this).getMe() authApi.getMe()
.enqueue(new Callback<UserDTO>() { .enqueue(new Callback<UserDTO>() {
@Override @Override
public void onResponse(Call<UserDTO> call, public void onResponse(Call<UserDTO> call,
Response<UserDTO> response) { Response<UserDTO> response) {
if (response.isSuccessful() && response.body() != null) { if (response.isSuccessful() && response.body() != null) {
TokenManager.getInstance(MainActivity.this) tokenManager.saveUserId(response.body().getId());
.saveUserId(response.body().getId());
} }
Toast.makeText(MainActivity.this, "Login successful", Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, "Login successful", Toast.LENGTH_SHORT).show();
@@ -169,7 +173,7 @@ public class MainActivity extends AppCompatActivity {
if (t instanceof java.net.ConnectException || if (t instanceof java.net.ConnectException ||
t instanceof java.net.SocketTimeoutException || t instanceof java.net.SocketTimeoutException ||
t instanceof java.net.UnknownHostException) { t instanceof java.net.UnknownHostException) {
errorMessage = "Cannot connect to server at " + RetrofitClient.BASE_URL + errorMessage = "Cannot connect to server at " + baseUrl +
". Please check if the backend is running."; ". Please check if the backend is running.";
} else if (t instanceof java.io.IOException) { } else if (t instanceof java.io.IOException) {
errorMessage = "Network error. Please check your connection."; errorMessage = "Network error. Please check your connection.";
@@ -183,4 +187,4 @@ public class MainActivity extends AppCompatActivity {
}); });
}); });
} }
} }

View File

@@ -13,7 +13,6 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.example.petstoremobile.R; import com.example.petstoremobile.R;
import com.example.petstoremobile.api.PetApi; import com.example.petstoremobile.api.PetApi;
import com.example.petstoremobile.api.RetrofitClient;
import com.example.petstoremobile.dtos.PetDTO; import com.example.petstoremobile.dtos.PetDTO;
import java.util.List; import java.util.List;
@@ -21,6 +20,7 @@ public class PetAdapter extends RecyclerView.Adapter<PetAdapter.PetViewHolder> {
private List<PetDTO> petList; private List<PetDTO> petList;
private OnPetClickListener petClickListener; private OnPetClickListener petClickListener;
private String baseUrl;
// Interface for pet click on recycler view // Interface for pet click on recycler view
public interface OnPetClickListener { public interface OnPetClickListener {
@@ -33,6 +33,10 @@ public class PetAdapter extends RecyclerView.Adapter<PetAdapter.PetViewHolder> {
this.petClickListener = petClickListener; this.petClickListener = petClickListener;
} }
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
// Get the controls of each row in recycler view // Get the controls of each row in recycler view
public static class PetViewHolder extends RecyclerView.ViewHolder { public static class PetViewHolder extends RecyclerView.ViewHolder {
TextView tvPetName, tvPetSpeciesBreed, tvPetAge, tvPetPrice, tvPetStatus; TextView tvPetName, tvPetSpeciesBreed, tvPetAge, tvPetPrice, tvPetStatus;
@@ -83,15 +87,19 @@ public class PetAdapter extends RecyclerView.Adapter<PetAdapter.PetViewHolder> {
} }
// Load pet image using Glide with circle crop // Load pet image using Glide with circle crop
String imageUrl = RetrofitClient.BASE_URL + String.format(PetApi.PET_IMAGE_PATH, pet.getPetId()); if (baseUrl != null) {
Glide.with(holder.itemView.getContext()) String imageUrl = baseUrl + String.format(PetApi.PET_IMAGE_PATH, pet.getPetId());
.load(imageUrl) Glide.with(holder.itemView.getContext())
.circleCrop() .load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.NONE) .circleCrop()
.skipMemoryCache(true) .diskCacheStrategy(DiskCacheStrategy.NONE)
.placeholder(R.drawable.placeholder) .skipMemoryCache(true)
.error(R.drawable.placeholder) .placeholder(R.drawable.placeholder)
.into(holder.ivPetProfile); .error(R.drawable.placeholder)
.into(holder.ivPetProfile);
} else {
holder.ivPetProfile.setImageResource(R.drawable.placeholder);
}
//when a row is clicked, open the detail view //when a row is clicked, open the detail view
holder.itemView.setOnClickListener(v -> petClickListener.onPetClick(position)); holder.itemView.setOnClickListener(v -> petClickListener.onPetClick(position));

View File

@@ -10,7 +10,6 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.example.petstoremobile.R; import com.example.petstoremobile.R;
import com.example.petstoremobile.api.ProductApi; import com.example.petstoremobile.api.ProductApi;
import com.example.petstoremobile.api.RetrofitClient;
import com.example.petstoremobile.dtos.ProductDTO; import com.example.petstoremobile.dtos.ProductDTO;
import java.util.List; import java.util.List;
@@ -18,6 +17,7 @@ public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductV
private List<ProductDTO> productList; private List<ProductDTO> productList;
private OnProductClickListener listener; private OnProductClickListener listener;
private String baseUrl;
public interface OnProductClickListener { public interface OnProductClickListener {
void onProductClick(int position); void onProductClick(int position);
@@ -28,6 +28,10 @@ public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductV
this.listener = listener; this.listener = listener;
} }
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public static class ProductViewHolder extends RecyclerView.ViewHolder { public static class ProductViewHolder extends RecyclerView.ViewHolder {
TextView tvName, tvCategory, tvDesc, tvPrice; TextView tvName, tvCategory, tvDesc, tvPrice;
ImageView ivProductImage; ImageView ivProductImage;
@@ -59,15 +63,19 @@ public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductV
holder.tvPrice.setText(p.getProdPrice() != null ? "$" + p.getProdPrice() : ""); holder.tvPrice.setText(p.getProdPrice() != null ? "$" + p.getProdPrice() : "");
// Load product image using Glide // Load product image using Glide
String imageUrl = RetrofitClient.BASE_URL + String.format(ProductApi.PRODUCT_IMAGE_PATH, p.getProdId()); if (baseUrl != null) {
Glide.with(holder.itemView.getContext()) String imageUrl = baseUrl + String.format(ProductApi.PRODUCT_IMAGE_PATH, p.getProdId());
.load(imageUrl) Glide.with(holder.itemView.getContext())
.circleCrop() .load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.NONE) .circleCrop()
.skipMemoryCache(true) .diskCacheStrategy(DiskCacheStrategy.NONE)
.placeholder(R.drawable.placeholder) .skipMemoryCache(true)
.error(R.drawable.placeholder) .placeholder(R.drawable.placeholder)
.into(holder.ivProductImage); .error(R.drawable.placeholder)
.into(holder.ivProductImage);
} else {
holder.ivProductImage.setImageResource(R.drawable.placeholder);
}
holder.itemView.setOnClickListener(v -> listener.onProductClick(position)); holder.itemView.setOnClickListener(v -> listener.onProductClick(position));
} }

View File

@@ -1,7 +1,5 @@
package com.example.petstoremobile.api.auth; package com.example.petstoremobile.api.auth;
import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import java.io.IOException; import java.io.IOException;
@@ -15,8 +13,8 @@ public class AuthInterceptor implements Interceptor {
private final TokenManager tokenManager; private final TokenManager tokenManager;
public AuthInterceptor(Context context) { public AuthInterceptor(TokenManager tokenManager) {
this.tokenManager = TokenManager.getInstance(context); this.tokenManager = tokenManager;
} }
@NonNull @NonNull

View File

@@ -3,7 +3,12 @@ package com.example.petstoremobile.api.auth;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
//Store login token in shared preferences import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.hilt.android.qualifiers.ApplicationContext;
@Singleton
public class TokenManager { public class TokenManager {
private static final String TOKEN_KEY = "token"; private static final String TOKEN_KEY = "token";
private static final String USERNAME_KEY = "username"; private static final String USERNAME_KEY = "username";
@@ -11,20 +16,13 @@ public class TokenManager {
private static final String PREFS_NAME = "auth_prefs"; private static final String PREFS_NAME = "auth_prefs";
private static final String USER_ID_KEY = "user_id"; private static final String USER_ID_KEY = "user_id";
private static TokenManager instance;
private SharedPreferences prefs; private SharedPreferences prefs;
private TokenManager(Context context) { @Inject
public TokenManager(@ApplicationContext Context context) {
prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
} }
public static TokenManager getInstance(Context context) {
if (instance == null) {
instance = new TokenManager(context);
}
return instance;
}
//save login data after login //save login data after login
public void saveLoginData(String token, String username, String role) { public void saveLoginData(String token, String username, String role) {
prefs.edit() prefs.edit()
@@ -65,6 +63,4 @@ public class TokenManager {
public void clearLoginData() { public void clearLoginData() {
prefs.edit().clear().apply(); prefs.edit().clear().apply();
} }
}
}

View File

@@ -0,0 +1,176 @@
package com.example.petstoremobile.di;
import android.content.Context;
import android.os.Build;
import com.example.petstoremobile.BuildConfig;
import com.example.petstoremobile.api.*;
import com.example.petstoremobile.api.auth.AuthApi;
import com.example.petstoremobile.api.auth.AuthInterceptor;
import com.example.petstoremobile.api.auth.TokenManager;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import dagger.hilt.InstallIn;
import dagger.hilt.android.qualifiers.ApplicationContext;
import dagger.hilt.components.SingletonComponent;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
//Module to provide dependencies injection for the api
@Module
@InstallIn(SingletonComponent.class)
public class NetworkModule {
@Provides
@Singleton
@Named("baseUrl")
public static String provideBaseUrl() {
return isEmulator() ? BuildConfig.EMULATOR_BACKEND_URL : BuildConfig.DEVICE_BACKEND_URL;
}
// Check if the device is an emulator
private static boolean isEmulator() {
return Build.FINGERPRINT.startsWith("generic")
|| Build.FINGERPRINT.startsWith("unknown")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86")
|| Build.MANUFACTURER.contains("Genymotion")
|| Build.HARDWARE.contains("goldfish")
|| Build.HARDWARE.contains("ranchu")
|| Build.PRODUCT.contains("sdk")
|| Build.PRODUCT.contains("sdk_gphone")
|| (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"));
}
@Provides
@Singleton
public static OkHttpClient provideOkHttpClient(TokenManager tokenManager) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
return new OkHttpClient.Builder()
.addInterceptor(interceptor)
.addInterceptor(new AuthInterceptor(tokenManager))
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build();
}
//build the retrofit instance
@Provides
@Singleton
public static Retrofit provideRetrofit(@Named("baseUrl") String baseUrl, OkHttpClient client) {
return new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
}
//associate the api with the retrofit instance
@Provides
@Singleton
public static PetApi providePetApi(Retrofit retrofit) {
return retrofit.create(PetApi.class);
}
@Provides
@Singleton
public static ServiceApi provideServiceApi(Retrofit retrofit) {
return retrofit.create(ServiceApi.class);
}
@Provides
@Singleton
public static SupplierApi provideSupplierApi(Retrofit retrofit) {
return retrofit.create(SupplierApi.class);
}
@Provides
@Singleton
public static AdoptionApi provideAdoptionApi(Retrofit retrofit) {
return retrofit.create(AdoptionApi.class);
}
@Provides
@Singleton
public static AppointmentApi provideAppointmentApi(Retrofit retrofit) {
return retrofit.create(AppointmentApi.class);
}
@Provides
@Singleton
public static ProductApi provideProductApi(Retrofit retrofit) {
return retrofit.create(ProductApi.class);
}
@Provides
@Singleton
public static SaleApi provideSaleApi(Retrofit retrofit) {
return retrofit.create(SaleApi.class);
}
@Provides
@Singleton
public static PurchaseOrderApi providePurchaseOrderApi(Retrofit retrofit) {
return retrofit.create(PurchaseOrderApi.class);
}
@Provides
@Singleton
public static ProductSupplierApi provideProductSupplierApi(Retrofit retrofit) {
return retrofit.create(ProductSupplierApi.class);
}
@Provides
@Singleton
public static InventoryApi provideInventoryApi(Retrofit retrofit) {
return retrofit.create(InventoryApi.class);
}
@Provides
@Singleton
public static AuthApi provideAuthApi(Retrofit retrofit) {
return retrofit.create(AuthApi.class);
}
@Provides
@Singleton
public static ChatApi provideChatApi(Retrofit retrofit) {
return retrofit.create(ChatApi.class);
}
@Provides
@Singleton
public static CustomerApi provideCustomerApi(Retrofit retrofit) {
return retrofit.create(CustomerApi.class);
}
@Provides
@Singleton
public static MessageApi provideMessageApi(Retrofit retrofit) {
return retrofit.create(MessageApi.class);
}
@Provides
@Singleton
public static StoreApi provideStoreApi(Retrofit retrofit) {
return retrofit.create(StoreApi.class);
}
@Provides
@Singleton
public static CategoryApi provideCategoryApi(Retrofit retrofit) {
return retrofit.create(CategoryApi.class);
}
}

View File

@@ -26,7 +26,6 @@ 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.api.RetrofitClient;
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;
@@ -36,10 +35,17 @@ import com.example.petstoremobile.models.Chat;
import com.example.petstoremobile.models.Message; import com.example.petstoremobile.models.Message;
import com.example.petstoremobile.services.ChatNotificationService; import com.example.petstoremobile.services.ChatNotificationService;
import com.example.petstoremobile.websocket.StompChatManager; import com.example.petstoremobile.websocket.StompChatManager;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Named;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.*; import retrofit2.*;
@AndroidEntryPoint
public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickListener, StompChatManager.MessageListener, public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickListener, StompChatManager.MessageListener,
StompChatManager.ConversationListener, StompChatManager.ConnectionListener { StompChatManager.ConversationListener, StompChatManager.ConnectionListener {
@@ -70,9 +76,11 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
private Uri pendingAttachmentUri; private Uri pendingAttachmentUri;
// APIs // APIs
private ChatApi chatApi; @Inject ChatApi chatApi;
private CustomerApi customerApi; @Inject CustomerApi customerApi;
private MessageApi messageApi; @Inject MessageApi messageApi;
@Inject TokenManager tokenManager;
@Inject @Named("baseUrl") String baseUrl;
// chat // chat
private Long currentUserId; private Long currentUserId;
@@ -103,10 +111,6 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
View view = inflater.inflate(R.layout.fragment_chat, container, false); View view = inflater.inflate(R.layout.fragment_chat, container, false);
chatApi = RetrofitClient.getChatApi(requireContext());
customerApi = RetrofitClient.getCustomerApi(requireContext());
messageApi = RetrofitClient.getMessageApi(requireContext());
drawerLayout = view.findViewById(R.id.chatDrawerLayout); drawerLayout = view.findViewById(R.id.chatDrawerLayout);
rvChatList = view.findViewById(R.id.rvChatList); rvChatList = view.findViewById(R.id.rvChatList);
rvMessages = view.findViewById(R.id.rvMessages); rvMessages = view.findViewById(R.id.rvMessages);
@@ -169,16 +173,15 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
//Helper function to load token and user id then connect to websocket //Helper function to load token and user id then connect to websocket
private void loadInitialData() { private void loadInitialData() {
TokenManager tm = TokenManager.getInstance(requireContext()); String token = tokenManager.getToken();
String token = tm.getToken(); currentUserId = tokenManager.getUserId();
currentUserId = tm.getUserId(); String role = tokenManager.getRole();
String role = tm.getRole();
messageAdapter.setCurrentUserId(currentUserId); messageAdapter.setCurrentUserId(currentUserId);
// if token exist then connect to websocket // if token exist then connect to websocket
if (token != null) { if (token != null) {
stompChatManager = new StompChatManager(token, role); stompChatManager = new StompChatManager(token, role, baseUrl);
stompChatManager.setMessageListener(this); stompChatManager.setMessageListener(this);
stompChatManager.setConversationListener(this); stompChatManager.setConversationListener(this);
stompChatManager.setConnectionListener(this); stompChatManager.setConnectionListener(this);
@@ -561,4 +564,4 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
ChatNotificationService.activeConversationIdInUi = null; ChatNotificationService.activeConversationIdInUi = null;
if (stompChatManager != null) stompChatManager.disconnect(); if (stompChatManager != null) stompChatManager.disconnect();
} }
} }

View File

@@ -26,7 +26,12 @@ import com.example.petstoremobile.fragments.listfragments.ProductSupplierFragmen
import com.example.petstoremobile.fragments.listfragments.PurchaseOrderFragment; import com.example.petstoremobile.fragments.listfragments.PurchaseOrderFragment;
import com.example.petstoremobile.fragments.listfragments.SaleFragment; import com.example.petstoremobile.fragments.listfragments.SaleFragment;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
//The Fragment for the displaying the list of entities to be viewed //The Fragment for the displaying the list of entities to be viewed
@AndroidEntryPoint
public class ListFragment extends Fragment { public class ListFragment extends Fragment {
private DrawerLayout drawerLayout; private DrawerLayout drawerLayout;
@@ -37,6 +42,7 @@ public class ListFragment extends Fragment {
private LinearLayout drawerAdoptions, drawerAppointments, drawerInventory, drawerProducts, drawerProductSupplier, drawerPurchaseOrderView, drawerSale; private LinearLayout drawerAdoptions, drawerAppointments, drawerInventory, drawerProducts, drawerProductSupplier, drawerPurchaseOrderView, drawerSale;
@Inject TokenManager tokenManager;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -58,7 +64,7 @@ public class ListFragment extends Fragment {
// Check user role and restrict access for STAFF // Check user role and restrict access for STAFF
String role = TokenManager.getInstance(requireContext()).getRole(); String role = tokenManager.getRole();
if ("STAFF".equalsIgnoreCase(role)) { if ("STAFF".equalsIgnoreCase(role)) {
drawerSuppliers.setVisibility(View.GONE); drawerSuppliers.setVisibility(View.GONE);
drawerInventory.setVisibility(View.GONE); drawerInventory.setVisibility(View.GONE);
@@ -178,4 +184,4 @@ public class ListFragment extends Fragment {
.addToBackStack(null) .addToBackStack(null)
.commit(); .commit();
} }
} }

View File

@@ -32,7 +32,6 @@ import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.load.model.LazyHeaders; import com.bumptech.glide.load.model.LazyHeaders;
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.RetrofitClient;
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.dtos.ErrorResponse; import com.example.petstoremobile.dtos.ErrorResponse;
@@ -49,6 +48,10 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import dagger.hilt.android.AndroidEntryPoint;
import okhttp3.MediaType; import okhttp3.MediaType;
import okhttp3.MultipartBody; import okhttp3.MultipartBody;
import okhttp3.RequestBody; import okhttp3.RequestBody;
@@ -56,6 +59,7 @@ import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@AndroidEntryPoint
public class ProfileFragment extends Fragment { public class ProfileFragment extends Fragment {
//initialize the view/controls //initialize the view/controls
@@ -65,6 +69,10 @@ public class ProfileFragment extends Fragment {
private UserDTO currentUser; private UserDTO currentUser;
private boolean hasImage = false; private boolean hasImage = false;
@Inject AuthApi authApi;
@Inject TokenManager tokenManager;
@Inject @Named("baseUrl") String baseUrl;
//Initialize the launchers for camera and gallery //Initialize the launchers for camera and gallery
private ActivityResultLauncher<Intent> galleryLauncher; private ActivityResultLauncher<Intent> galleryLauncher;
private ActivityResultLauncher<Uri> cameraLauncher; private ActivityResultLauncher<Uri> cameraLauncher;
@@ -251,7 +259,7 @@ public class ProfileFragment extends Fragment {
Intent serviceIntent = new Intent(requireContext(), ChatNotificationService.class); Intent serviceIntent = new Intent(requireContext(), ChatNotificationService.class);
requireContext().stopService(serviceIntent); requireContext().stopService(serviceIntent);
TokenManager.getInstance(requireContext()).clearLoginData(); // clear the token for next login tokenManager.clearLoginData(); // clear the token for next login
//get the intent to the main activity and clear the back stack so the back button won't allow the user to go back to the previous screen //get the intent to the main activity and clear the back stack so the back button won't allow the user to go back to the previous screen
Intent intent = new Intent(getActivity(), MainActivity.class); Intent intent = new Intent(getActivity(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -275,8 +283,6 @@ public class ProfileFragment extends Fragment {
//Helper function to call the backend to get profile data and load it to the view //Helper function to call the backend to get profile data and load it to the view
private void loadProfileData() { private void loadProfileData() {
AuthApi authApi = RetrofitClient.getAuthApi(requireContext());
authApi.getMe().enqueue(new Callback<UserDTO>() { authApi.getMe().enqueue(new Callback<UserDTO>() {
@Override @Override
public void onResponse(Call<UserDTO> call, Response<UserDTO> response) { public void onResponse(Call<UserDTO> call, Response<UserDTO> response) {
@@ -291,8 +297,8 @@ public class ProfileFragment extends Fragment {
tvProfileRole.setText(currentUser.getRole()); 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 = RetrofitClient.BASE_URL + AuthApi.AVATAR_FILE_PATH; String avatarUrl = baseUrl + AuthApi.AVATAR_FILE_PATH;
String token = TokenManager.getInstance(requireContext()).getToken(); String token = tokenManager.getToken();
if (token != null) { if (token != null) {
// Create GlideUrl with token to fetch the image // Create GlideUrl with token to fetch the image
@@ -354,7 +360,6 @@ public class ProfileFragment extends Fragment {
MultipartBody.Part body = MultipartBody.Part.createFormData("avatar", file.getName(), requestFile); MultipartBody.Part body = MultipartBody.Part.createFormData("avatar", file.getName(), requestFile);
//Call the backend to upload the avatar //Call the backend to upload the avatar
AuthApi authApi = RetrofitClient.getAuthApi(requireContext());
authApi.uploadAvatar(body).enqueue(new Callback<UserDTO>() { authApi.uploadAvatar(body).enqueue(new Callback<UserDTO>() {
@Override @Override
public void onResponse(Call<UserDTO> call, Response<UserDTO> response) { public void onResponse(Call<UserDTO> call, Response<UserDTO> response) {
@@ -380,7 +385,6 @@ public class ProfileFragment extends Fragment {
} }
private void deleteAvatar() { private void deleteAvatar() {
AuthApi authApi = RetrofitClient.getAuthApi(requireContext());
authApi.deleteAvatar().enqueue(new Callback<Void>() { authApi.deleteAvatar().enqueue(new Callback<Void>() {
@Override @Override
public void onResponse(Call<Void> call, Response<Void> response) { public void onResponse(Call<Void> call, Response<Void> response) {
@@ -423,7 +427,6 @@ public class ProfileFragment extends Fragment {
//Helper function to update a profile field in the backend //Helper function to update a profile field in the backend
private void updateProfileField(String fieldName, String value) { private void updateProfileField(String fieldName, String value) {
AuthApi authApi = RetrofitClient.getAuthApi(requireContext());
Map<String, String> updates = new HashMap<>(); Map<String, String> updates = new HashMap<>();
updates.put(fieldName, value); updates.put(fieldName, value);
@@ -456,4 +459,4 @@ public class ProfileFragment extends Fragment {
} }
}); });
} }
} }

View File

@@ -14,7 +14,6 @@ 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.api.AdoptionApi; import com.example.petstoremobile.api.AdoptionApi;
import com.example.petstoremobile.api.RetrofitClient;
import com.example.petstoremobile.dtos.AdoptionDTO; import com.example.petstoremobile.dtos.AdoptionDTO;
import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.fragments.ListFragment;
@@ -28,14 +27,19 @@ 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.*;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.*; import retrofit2.*;
@AndroidEntryPoint
public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdoptionClickListener { public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdoptionClickListener {
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 AdoptionApi api; @Inject AdoptionApi api;
private SwipeRefreshLayout swipeRefresh; private SwipeRefreshLayout swipeRefresh;
private EditText etSearch; private EditText etSearch;
private ImageButton hamburger; private ImageButton hamburger;
@@ -50,7 +54,6 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
Bundle savedInstanceState) { Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_adoption, container, false); View view = inflater.inflate(R.layout.fragment_adoption, container, false);
api = RetrofitClient.getAdoptionApi(requireContext());
hamburger = view.findViewById(R.id.btnHamburgerAdoption); hamburger = view.findViewById(R.id.btnHamburgerAdoption);
calendarView = view.findViewById(R.id.calendarViewAdoption); calendarView = view.findViewById(R.id.calendarViewAdoption);
btnToggleCalendarMode = view.findViewById(R.id.btnToggleCalendarModeAdoption); btnToggleCalendarMode = view.findViewById(R.id.btnToggleCalendarModeAdoption);

View File

@@ -23,7 +23,6 @@ import com.example.petstoremobile.adapters.AppointmentAdapter;
import com.example.petstoremobile.api.AppointmentApi; import com.example.petstoremobile.api.AppointmentApi;
import com.example.petstoremobile.api.PetApi; import com.example.petstoremobile.api.PetApi;
import com.example.petstoremobile.api.ServiceApi; import com.example.petstoremobile.api.ServiceApi;
import com.example.petstoremobile.api.RetrofitClient;
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.PageResponse; import com.example.petstoremobile.dtos.PageResponse;
@@ -46,10 +45,14 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@AndroidEntryPoint
public class AppointmentFragment extends Fragment implements AppointmentAdapter.OnAppointmentClickListener { public class AppointmentFragment extends Fragment implements AppointmentAdapter.OnAppointmentClickListener {
private List<AppointmentDTO> appointmentList = new ArrayList<>(); private List<AppointmentDTO> appointmentList = new ArrayList<>();
@@ -58,7 +61,10 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
private List<ServiceDTO> serviceList = new ArrayList<>(); private List<ServiceDTO> serviceList = new ArrayList<>();
private AppointmentAdapter adapter; private AppointmentAdapter adapter;
private AppointmentApi api; @Inject AppointmentApi api;
@Inject PetApi petApi;
@Inject ServiceApi serviceApi;
private SwipeRefreshLayout swipeRefreshLayout; private SwipeRefreshLayout swipeRefreshLayout;
private EditText etSearch; private EditText etSearch;
private ImageButton hamburger; private ImageButton hamburger;
@@ -73,7 +79,6 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
Bundle savedInstanceState) { Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_appointment, container, false); View view = inflater.inflate(R.layout.fragment_appointment, container, false);
api = RetrofitClient.getAppointmentApi(requireContext());
hamburger = view.findViewById(R.id.btnHamburger); hamburger = view.findViewById(R.id.btnHamburger);
calendarView = view.findViewById(R.id.calendarView); calendarView = view.findViewById(R.id.calendarView);
btnToggleCalendarMode = view.findViewById(R.id.btnToggleCalendarMode); btnToggleCalendarMode = view.findViewById(R.id.btnToggleCalendarMode);
@@ -267,7 +272,6 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
// Load Pets // Load Pets
private void loadPets() { private void loadPets() {
PetApi petApi = RetrofitClient.getPetApi(requireContext());
petApi.getAllPets(0,100).enqueue(new Callback<PageResponse<PetDTO>>() { petApi.getAllPets(0,100).enqueue(new Callback<PageResponse<PetDTO>>() {
@Override @Override
@@ -290,8 +294,6 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
// Load Services // Load Services
private void loadServices() { private void loadServices() {
ServiceApi serviceApi = RetrofitClient.getServiceApi(requireContext());
serviceApi.getAllServices(0,100).enqueue(new Callback<PageResponse<ServiceDTO>>() { serviceApi.getAllServices(0,100).enqueue(new Callback<PageResponse<ServiceDTO>>() {
@Override @Override
public void onResponse(Call<PageResponse<ServiceDTO>> call, Response<PageResponse<ServiceDTO>> response) { public void onResponse(Call<PageResponse<ServiceDTO>> call, Response<PageResponse<ServiceDTO>> response) {
@@ -331,4 +333,4 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter.
recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
} }
} }

View File

@@ -10,7 +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.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
@@ -28,7 +27,6 @@ import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
import com.example.petstoremobile.adapters.InventoryAdapter; import com.example.petstoremobile.adapters.InventoryAdapter;
import com.example.petstoremobile.api.CategoryApi; import com.example.petstoremobile.api.CategoryApi;
import com.example.petstoremobile.api.InventoryApi; import com.example.petstoremobile.api.InventoryApi;
import com.example.petstoremobile.api.RetrofitClient;
import com.example.petstoremobile.dtos.BulkDeleteRequest; import com.example.petstoremobile.dtos.BulkDeleteRequest;
import com.example.petstoremobile.dtos.CategoryDTO; import com.example.petstoremobile.dtos.CategoryDTO;
import com.example.petstoremobile.dtos.InventoryDTO; import com.example.petstoremobile.dtos.InventoryDTO;
@@ -40,10 +38,14 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@AndroidEntryPoint
public class InventoryFragment extends Fragment implements InventoryAdapter.OnInventoryClickListener { public class InventoryFragment extends Fragment implements InventoryAdapter.OnInventoryClickListener {
private static final String TAG = "InventoryFragment"; private static final String TAG = "InventoryFragment";
@@ -52,8 +54,8 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
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 InventoryApi inventoryApi; @Inject InventoryApi inventoryApi;
private CategoryApi categoryApi; @Inject CategoryApi categoryApi;
private SwipeRefreshLayout swipeRefreshLayout; private SwipeRefreshLayout swipeRefreshLayout;
private EditText etSearch; private EditText etSearch;
@@ -83,9 +85,6 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
Bundle savedInstanceState) { Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_inventory, container, false); View view = inflater.inflate(R.layout.fragment_inventory, container, false);
inventoryApi = RetrofitClient.getInventoryApi(requireContext());
categoryApi = RetrofitClient.getCategoryApi(requireContext());
hamburger = view.findViewById(R.id.btnHamburger); hamburger = view.findViewById(R.id.btnHamburger);
btnBulkDelete = view.findViewById(R.id.btnBulkDelete); btnBulkDelete = view.findViewById(R.id.btnBulkDelete);
tvSelectionCount = view.findViewById(R.id.tvSelectionCount); tvSelectionCount = view.findViewById(R.id.tvSelectionCount);
@@ -175,8 +174,7 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
private void setupSearch(View view) { private void setupSearch(View view) {
etSearch = view.findViewById(R.id.etSearchInventory); etSearch = view.findViewById(R.id.etSearchInventory);
etSearch.addTextChangedListener(new TextWatcher() { etSearch.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) {
} }
@Override @Override

View File

@@ -14,7 +14,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.ArrayAdapter;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.Spinner; import android.widget.Spinner;
@@ -24,7 +23,6 @@ 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.api.PetApi; import com.example.petstoremobile.api.PetApi;
import com.example.petstoremobile.api.RetrofitClient;
import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.PetDTO; import com.example.petstoremobile.dtos.PetDTO;
import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.fragments.ListFragment;
@@ -35,16 +33,22 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@AndroidEntryPoint
public class PetFragment extends Fragment implements PetAdapter.OnPetClickListener { public class PetFragment extends Fragment implements PetAdapter.OnPetClickListener {
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 ImageButton hamburger;
private PetAdapter adapter; private PetAdapter adapter;
private PetApi api; @Inject PetApi api;
@Inject @Named("baseUrl") String baseUrl;
private SwipeRefreshLayout swipeRefreshLayout; private SwipeRefreshLayout swipeRefreshLayout;
private EditText etSearch; private EditText etSearch;
private Spinner spinnerStatus; private Spinner spinnerStatus;
@@ -55,9 +59,6 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
Bundle savedInstanceState) { Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pet, container, false); View view = inflater.inflate(R.layout.fragment_pet, container, false);
//get retrofit
api = RetrofitClient.getPetApi(requireContext());
hamburger = view.findViewById(R.id.btnHamburger); hamburger = view.findViewById(R.id.btnHamburger);
setupRecyclerView(view); setupRecyclerView(view);
@@ -231,6 +232,7 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
private void setupRecyclerView(View view) { private void setupRecyclerView(View view) {
RecyclerView recyclerView = view.findViewById(R.id.recyclerViewPets); RecyclerView recyclerView = view.findViewById(R.id.recyclerViewPets);
adapter = new PetAdapter(filteredList, this); adapter = new PetAdapter(filteredList, this);
adapter.setBaseUrl(baseUrl);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
} }

View File

@@ -11,15 +11,20 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; 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.RetrofitClient; import com.example.petstoremobile.api.ProductApi;
import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.dtos.PageResponse;
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.fragments.listfragments.detailfragments.ProductDetailFragment; import com.example.petstoremobile.fragments.listfragments.detailfragments.ProductDetailFragment;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.*; import java.util.*;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.*; import retrofit2.*;
@AndroidEntryPoint
public class ProductFragment extends Fragment implements ProductAdapter.OnProductClickListener { public class ProductFragment extends Fragment implements ProductAdapter.OnProductClickListener {
private List<ProductDTO> productList = new ArrayList<>(); private List<ProductDTO> productList = new ArrayList<>();
@@ -28,6 +33,8 @@ public class ProductFragment extends Fragment implements ProductAdapter.OnProduc
private SwipeRefreshLayout swipeRefresh; private SwipeRefreshLayout swipeRefresh;
private EditText etSearch; private EditText etSearch;
@Inject ProductApi api;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
@@ -93,7 +100,7 @@ public class ProductFragment extends Fragment implements ProductAdapter.OnProduc
private void loadProducts() { private void loadProducts() {
if (swipeRefresh != null) swipeRefresh.setRefreshing(true); if (swipeRefresh != null) swipeRefresh.setRefreshing(true);
RetrofitClient.getProductApi(requireContext()).getAllProducts(null, 0, 100) api.getAllProducts(null, 0, 100)
.enqueue(new Callback<PageResponse<ProductDTO>>() { .enqueue(new Callback<PageResponse<ProductDTO>>() {
public void onResponse(Call<PageResponse<ProductDTO>> c, public void onResponse(Call<PageResponse<ProductDTO>> c,
Response<PageResponse<ProductDTO>> r) { Response<PageResponse<ProductDTO>> r) {

View File

@@ -11,15 +11,20 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; 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.api.RetrofitClient; import com.example.petstoremobile.api.ProductSupplierApi;
import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.dtos.PageResponse;
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.fragments.listfragments.detailfragments.ProductSupplierDetailFragment; import com.example.petstoremobile.fragments.listfragments.detailfragments.ProductSupplierDetailFragment;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.*; import java.util.*;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.*; import retrofit2.*;
@AndroidEntryPoint
public class ProductSupplierFragment extends Fragment public class ProductSupplierFragment extends Fragment
implements ProductSupplierAdapter.OnProductSupplierClickListener { implements ProductSupplierAdapter.OnProductSupplierClickListener {
@@ -29,6 +34,8 @@ public class ProductSupplierFragment extends Fragment
private SwipeRefreshLayout swipeRefresh; private SwipeRefreshLayout swipeRefresh;
private EditText etSearch; private EditText etSearch;
@Inject ProductSupplierApi api;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
@@ -92,7 +99,7 @@ public class ProductSupplierFragment extends Fragment
private void loadData() { private void loadData() {
if (swipeRefresh != null) swipeRefresh.setRefreshing(true); if (swipeRefresh != null) swipeRefresh.setRefreshing(true);
RetrofitClient.getProductSupplierApi(requireContext()).getAllProductSuppliers(0, 100) api.getAllProductSuppliers(0, 100)
.enqueue(new Callback<PageResponse<ProductSupplierDTO>>() { .enqueue(new Callback<PageResponse<ProductSupplierDTO>>() {
public void onResponse(Call<PageResponse<ProductSupplierDTO>> c, public void onResponse(Call<PageResponse<ProductSupplierDTO>> c,
Response<PageResponse<ProductSupplierDTO>> r) { Response<PageResponse<ProductSupplierDTO>> r) {

View File

@@ -11,14 +11,19 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; 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.api.RetrofitClient; import com.example.petstoremobile.api.PurchaseOrderApi;
import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.dtos.PageResponse;
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.fragments.listfragments.detailfragments.PurchaseOrderDetailFragment; import com.example.petstoremobile.fragments.listfragments.detailfragments.PurchaseOrderDetailFragment;
import java.util.*; import java.util.*;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.*; import retrofit2.*;
@AndroidEntryPoint
public class PurchaseOrderFragment extends Fragment public class PurchaseOrderFragment extends Fragment
implements PurchaseOrderAdapter.OnPurchaseOrderClickListener { implements PurchaseOrderAdapter.OnPurchaseOrderClickListener {
@@ -28,6 +33,8 @@ public class PurchaseOrderFragment extends Fragment
private SwipeRefreshLayout swipeRefresh; private SwipeRefreshLayout swipeRefresh;
private EditText etSearch; private EditText etSearch;
@Inject PurchaseOrderApi api;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
@@ -94,7 +101,7 @@ public class PurchaseOrderFragment extends Fragment
private void loadData() { private void loadData() {
if (swipeRefresh != null) if (swipeRefresh != null)
swipeRefresh.setRefreshing(true); swipeRefresh.setRefreshing(true);
RetrofitClient.getPurchaseOrderApi(requireContext()).getAllPurchaseOrders(0, 100) api.getAllPurchaseOrders(0, 100)
.enqueue(new Callback<PageResponse<PurchaseOrderDTO>>() { .enqueue(new Callback<PageResponse<PurchaseOrderDTO>>() {
public void onResponse(Call<PageResponse<PurchaseOrderDTO>> c, public void onResponse(Call<PageResponse<PurchaseOrderDTO>> c,
Response<PageResponse<PurchaseOrderDTO>> r) { Response<PageResponse<PurchaseOrderDTO>> r) {

View File

@@ -15,12 +15,18 @@ 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.fragments.ListFragment; import com.example.petstoremobile.fragments.ListFragment;
import com.example.petstoremobile.fragments.listfragments.detailfragments.RefundDetailFragment; import com.example.petstoremobile.fragments.listfragments.detailfragments.RefundDetailFragment;
import com.example.petstoremobile.models.Sale; import com.example.petstoremobile.models.Sale;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
@AndroidEntryPoint
public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickListener { public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickListener {
private List<Sale> saleList = new ArrayList<>(); private List<Sale> saleList = new ArrayList<>();
@@ -30,6 +36,8 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
private EditText etSearch; private EditText etSearch;
private ImageButton btnHamburger; private ImageButton btnHamburger;
@Inject SaleApi api;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {

View File

@@ -19,7 +19,6 @@ 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.api.RetrofitClient;
import com.example.petstoremobile.api.ServiceApi; import com.example.petstoremobile.api.ServiceApi;
import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.ServiceDTO; import com.example.petstoremobile.dtos.ServiceDTO;
@@ -30,17 +29,21 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@AndroidEntryPoint
public class ServiceFragment extends Fragment implements ServiceAdapter.OnServiceClickListener { public class ServiceFragment extends Fragment implements ServiceAdapter.OnServiceClickListener {
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 ImageButton hamburger;
private ServiceApi api; @Inject ServiceApi api;
private SwipeRefreshLayout swipeRefreshLayout; private SwipeRefreshLayout swipeRefreshLayout;
private EditText etSearch; private EditText etSearch;
@@ -50,7 +53,6 @@ public class ServiceFragment extends Fragment implements ServiceAdapter.OnServic
Bundle savedInstanceState) { Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_service, container, false); View view = inflater.inflate(R.layout.fragment_service, container, false);
api = RetrofitClient.getServiceApi(requireContext());
hamburger = view.findViewById(R.id.btnHamburger); hamburger = view.findViewById(R.id.btnHamburger);
setupRecyclerView(view); setupRecyclerView(view);

View File

@@ -19,7 +19,6 @@ 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.api.RetrofitClient;
import com.example.petstoremobile.api.SupplierApi; import com.example.petstoremobile.api.SupplierApi;
import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.SupplierDTO; import com.example.petstoremobile.dtos.SupplierDTO;
@@ -30,17 +29,21 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@AndroidEntryPoint
public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupplierClickListener { public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupplierClickListener {
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 ImageButton hamburger;
private SupplierApi api; @Inject SupplierApi api;
private SwipeRefreshLayout swipeRefreshLayout; private SwipeRefreshLayout swipeRefreshLayout;
private EditText etSearch; private EditText etSearch;
@@ -50,7 +53,6 @@ public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupp
Bundle savedInstanceState) { Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_supplier, container, false); View view = inflater.inflate(R.layout.fragment_supplier, container, false);
api = RetrofitClient.getSupplierApi(requireContext());
hamburger = view.findViewById(R.id.btnHamburger); hamburger = view.findViewById(R.id.btnHamburger);
setupRecyclerView(view); setupRecyclerView(view);

View File

@@ -14,8 +14,13 @@ import com.example.petstoremobile.api.*;
import com.example.petstoremobile.dtos.*; import com.example.petstoremobile.dtos.*;
import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.fragments.ListFragment;
import java.util.*; import java.util.*;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.*; import retrofit2.*;
@AndroidEntryPoint
public class AdoptionDetailFragment extends Fragment { public class AdoptionDetailFragment extends Fragment {
private TextView tvMode, tvAdoptionId; private TextView tvMode, tvAdoptionId;
@@ -33,6 +38,10 @@ public class AdoptionDetailFragment extends Fragment {
private final String[] STATUSES = {"Pending", "Approved", "Rejected"}; private final String[] STATUSES = {"Pending", "Approved", "Rejected"};
@Inject AdoptionApi adoptionApi;
@Inject PetApi petApi;
@Inject CustomerApi customerApi;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
@@ -84,7 +93,7 @@ public class AdoptionDetailFragment extends Fragment {
} }
private void loadPets() { private void loadPets() {
RetrofitClient.getPetApi(requireContext()).getAllPets(0, 200) petApi.getAllPets(0, 200)
.enqueue(new Callback<PageResponse<PetDTO>>() { .enqueue(new Callback<PageResponse<PetDTO>>() {
public void onResponse(Call<PageResponse<PetDTO>> c, public void onResponse(Call<PageResponse<PetDTO>> c,
Response<PageResponse<PetDTO>> r) { Response<PageResponse<PetDTO>> r) {
@@ -115,7 +124,7 @@ public class AdoptionDetailFragment extends Fragment {
} }
private void loadCustomers() { private void loadCustomers() {
RetrofitClient.getCustomerApi(requireContext()).getAllCustomers(0, 200) customerApi.getAllCustomers(0, 200)
.enqueue(new Callback<PageResponse<CustomerDTO>>() { .enqueue(new Callback<PageResponse<CustomerDTO>>() {
public void onResponse(Call<PageResponse<CustomerDTO>> c, public void onResponse(Call<PageResponse<CustomerDTO>> c,
Response<PageResponse<CustomerDTO>> r) { Response<PageResponse<CustomerDTO>> r) {
@@ -201,11 +210,10 @@ public class AdoptionDetailFragment extends Fragment {
+ " customerId=" + customer.getCustomerId() + " customerId=" + customer.getCustomerId()
+ " date=" + date + " status=" + status); + " date=" + date + " status=" + status);
AdoptionApi api = RetrofitClient.getAdoptionApi(requireContext());
if (isEditing) { if (isEditing) {
api.updateAdoption(adoptionId, dto).enqueue(simpleCallback("Updated")); adoptionApi.updateAdoption(adoptionId, dto).enqueue(simpleCallback("Updated"));
} else { } else {
api.createAdoption(dto).enqueue(simpleCallback("Saved")); adoptionApi.createAdoption(dto).enqueue(simpleCallback("Saved"));
} }
} }
@@ -237,8 +245,7 @@ public class AdoptionDetailFragment extends Fragment {
new AlertDialog.Builder(requireContext()) new AlertDialog.Builder(requireContext())
.setTitle("Delete Adoption?") .setTitle("Delete Adoption?")
.setPositiveButton("Yes", (d, w) -> .setPositiveButton("Yes", (d, w) ->
RetrofitClient.getAdoptionApi(requireContext()) adoptionApi.deleteAdoption(adoptionId)
.deleteAdoption(adoptionId)
.enqueue(new Callback<Void>() { .enqueue(new Callback<Void>() {
public void onResponse(Call<Void> c, Response<Void> r) { public void onResponse(Call<Void> c, Response<Void> r) {
navigateBack(); navigateBack();

View File

@@ -14,8 +14,13 @@ import com.example.petstoremobile.api.*;
import com.example.petstoremobile.dtos.*; import com.example.petstoremobile.dtos.*;
import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.fragments.ListFragment;
import java.util.*; import java.util.*;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.*; import retrofit2.*;
@AndroidEntryPoint
public class AppointmentDetailFragment extends Fragment { public class AppointmentDetailFragment extends Fragment {
private TextView tvMode, tvAppointmentId; private TextView tvMode, tvAppointmentId;
@@ -41,6 +46,12 @@ public class AppointmentDetailFragment extends Fragment {
private final Integer[] MINUTES = {0,15,30,45}; private final Integer[] MINUTES = {0,15,30,45};
private final String[] STATUSES = {"Booked","Completed","Cancelled"}; private final String[] STATUSES = {"Booked","Completed","Cancelled"};
@Inject AppointmentApi appointmentApi;
@Inject PetApi petApi;
@Inject ServiceApi serviceApi;
@Inject CustomerApi customerApi;
@Inject StoreApi storeApi;
@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); View view = inflater.inflate(R.layout.fragment_appointment_detail, container, false);
@@ -107,7 +118,7 @@ public class AppointmentDetailFragment extends Fragment {
} }
private void loadPets() { private void loadPets() {
RetrofitClient.getPetApi(requireContext()).getAllPets(0, 200) petApi.getAllPets(0, 200)
.enqueue(new Callback<PageResponse<PetDTO>>() { .enqueue(new Callback<PageResponse<PetDTO>>() {
public void onResponse(Call<PageResponse<PetDTO>> c, Response<PageResponse<PetDTO>> r) { public void onResponse(Call<PageResponse<PetDTO>> c, Response<PageResponse<PetDTO>> r) {
if (r.isSuccessful() && r.body() != null) { if (r.isSuccessful() && r.body() != null) {
@@ -137,7 +148,7 @@ public class AppointmentDetailFragment extends Fragment {
} }
private void loadServices() { private void loadServices() {
RetrofitClient.getServiceApi(requireContext()).getAllServices(0, 200) serviceApi.getAllServices(0, 200)
.enqueue(new Callback<PageResponse<ServiceDTO>>() { .enqueue(new Callback<PageResponse<ServiceDTO>>() {
public void onResponse(Call<PageResponse<ServiceDTO>> c, Response<PageResponse<ServiceDTO>> r) { public void onResponse(Call<PageResponse<ServiceDTO>> c, Response<PageResponse<ServiceDTO>> r) {
if (r.isSuccessful() && r.body() != null) { if (r.isSuccessful() && r.body() != null) {
@@ -167,7 +178,7 @@ public class AppointmentDetailFragment extends Fragment {
} }
private void loadCustomers() { private void loadCustomers() {
RetrofitClient.getCustomerApi(requireContext()).getAllCustomers(0, 200) customerApi.getAllCustomers(0, 200)
.enqueue(new Callback<PageResponse<CustomerDTO>>() { .enqueue(new Callback<PageResponse<CustomerDTO>>() {
public void onResponse(Call<PageResponse<CustomerDTO>> c, Response<PageResponse<CustomerDTO>> r) { public void onResponse(Call<PageResponse<CustomerDTO>> c, Response<PageResponse<CustomerDTO>> r) {
if (r.isSuccessful() && r.body() != null) { if (r.isSuccessful() && r.body() != null) {
@@ -198,7 +209,7 @@ public class AppointmentDetailFragment extends Fragment {
} }
private void loadStores() { private void loadStores() {
RetrofitClient.getStoreApi(requireContext()).getAllStores(0, 50) storeApi.getAllStores(0, 50)
.enqueue(new Callback<PageResponse<StoreDTO>>() { .enqueue(new Callback<PageResponse<StoreDTO>>() {
public void onResponse(Call<PageResponse<StoreDTO>> c, Response<PageResponse<StoreDTO>> r) { public void onResponse(Call<PageResponse<StoreDTO>> c, Response<PageResponse<StoreDTO>> r) {
if (r.isSuccessful() && r.body() != null) { if (r.isSuccessful() && r.body() != null) {
@@ -228,7 +239,7 @@ public class AppointmentDetailFragment extends Fragment {
} }
private void loadAllAppointments() { private void loadAllAppointments() {
RetrofitClient.getAppointmentApi(requireContext()).getAllAppointments(0, 500) appointmentApi.getAllAppointments(0, 500)
.enqueue(new Callback<PageResponse<AppointmentDTO>>() { .enqueue(new Callback<PageResponse<AppointmentDTO>>() {
public void onResponse(Call<PageResponse<AppointmentDTO>> c, Response<PageResponse<AppointmentDTO>> r) { public void onResponse(Call<PageResponse<AppointmentDTO>> c, Response<PageResponse<AppointmentDTO>> r) {
if (r.isSuccessful() && r.body() != null) if (r.isSuccessful() && r.body() != null)
@@ -350,11 +361,10 @@ public class AppointmentDetailFragment extends Fragment {
+ " petId=" + pet.getPetId() + " petId=" + pet.getPetId()
+ " date=" + date + " time=" + time); + " date=" + date + " time=" + time);
AppointmentApi api = RetrofitClient.getAppointmentApi(requireContext());
if (isEditing) { if (isEditing) {
api.updateAppointment(appointmentId, dto).enqueue(simpleCallback("Updated")); appointmentApi.updateAppointment(appointmentId, dto).enqueue(simpleCallback("Updated"));
} else { } else {
api.createAppointment(dto).enqueue(simpleCallback("Saved")); appointmentApi.createAppointment(dto).enqueue(simpleCallback("Saved"));
} }
} }
@@ -426,8 +436,7 @@ public class AppointmentDetailFragment extends Fragment {
new AlertDialog.Builder(requireContext()) new AlertDialog.Builder(requireContext())
.setTitle("Delete Appointment?") .setTitle("Delete Appointment?")
.setPositiveButton("Yes", (d, w) -> .setPositiveButton("Yes", (d, w) ->
RetrofitClient.getAppointmentApi(requireContext()) appointmentApi.deleteAppointment(appointmentId)
.deleteAppointment(appointmentId)
.enqueue(new Callback<Void>() { .enqueue(new Callback<Void>() {
public void onResponse(Call<Void> c, Response<Void> r) { navigateBack(); } public void onResponse(Call<Void> c, Response<Void> r) { navigateBack(); }
public void onFailure(Call<Void> c, Throwable t) { public void onFailure(Call<Void> c, Throwable t) {

View File

@@ -21,7 +21,6 @@ import com.example.petstoremobile.R;
import com.example.petstoremobile.adapters.BlackTextArrayAdapter; import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
import com.example.petstoremobile.api.InventoryApi; import com.example.petstoremobile.api.InventoryApi;
import com.example.petstoremobile.api.ProductApi; import com.example.petstoremobile.api.ProductApi;
import com.example.petstoremobile.api.RetrofitClient;
import com.example.petstoremobile.dtos.InventoryDTO; import com.example.petstoremobile.dtos.InventoryDTO;
import com.example.petstoremobile.dtos.InventoryRequest; import com.example.petstoremobile.dtos.InventoryRequest;
import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.dtos.PageResponse;
@@ -32,10 +31,14 @@ import com.example.petstoremobile.fragments.listfragments.InventoryFragment;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@AndroidEntryPoint
public class InventoryDetailFragment extends Fragment { public class InventoryDetailFragment extends Fragment {
private TextView tvMode, tvInventoryId, tvProductInfo; private TextView tvMode, tvInventoryId, tvProductInfo;
@@ -43,8 +46,8 @@ public class InventoryDetailFragment extends Fragment {
private android.widget.EditText etQuantity; private android.widget.EditText etQuantity;
private Button btnSave, btnDelete, btnBack; private Button btnSave, btnDelete, btnBack;
private InventoryApi inventoryApi; @Inject InventoryApi inventoryApi;
private ProductApi productApi; @Inject ProductApi productApi;
private InventoryFragment inventoryFragment; private InventoryFragment inventoryFragment;
private boolean isEditing = false; private boolean isEditing = false;
@@ -70,9 +73,6 @@ public class InventoryDetailFragment extends Fragment {
Bundle savedInstanceState) { Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_inventory_detail, container, false); View view = inflater.inflate(R.layout.fragment_inventory_detail, container, false);
inventoryApi = RetrofitClient.getInventoryApi(requireContext());
productApi = RetrofitClient.getProductApi(requireContext());
initViews(view); initViews(view);
setupProductSearch(); setupProductSearch();
handleArguments(); handleArguments();

View File

@@ -22,17 +22,20 @@ 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.api.PetApi; import com.example.petstoremobile.api.PetApi;
import com.example.petstoremobile.api.RetrofitClient;
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.fragments.listfragments.PetFragment; import com.example.petstoremobile.fragments.listfragments.PetFragment;
import com.example.petstoremobile.utils.ActivityLogger; import com.example.petstoremobile.utils.ActivityLogger;
import com.example.petstoremobile.utils.InputValidator; import com.example.petstoremobile.utils.InputValidator;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@AndroidEntryPoint
public class PetDetailFragment extends Fragment { public class PetDetailFragment extends Fragment {
private TextView tvMode, tvPetId; private TextView tvMode, tvPetId;
@@ -43,6 +46,8 @@ public class PetDetailFragment extends Fragment {
private boolean isEditing = false; private boolean isEditing = false;
private PetFragment petFragment; private PetFragment petFragment;
@Inject PetApi petApi;
//set the pet fragment to the parent so we refer back to pet view when save or delete is done //set the pet fragment to the parent so we refer back to pet view when save or delete is done
public void setPetFragment(PetFragment fragment) { public void setPetFragment(PetFragment fragment) {
this.petFragment = fragment; this.petFragment = fragment;
@@ -92,8 +97,6 @@ public class PetDetailFragment extends Fragment {
petDTO.setPetPrice(priceStr); petDTO.setPetPrice(priceStr);
petDTO.setPetStatus(status); petDTO.setPetStatus(status);
PetApi petApi = RetrofitClient.getPetApi(requireContext());
//check if the pet is being edited or added //check if the pet is being edited or added
if (isEditing) { if (isEditing) {
// Update existing pet // Update existing pet
@@ -148,7 +151,6 @@ public class PetDetailFragment extends Fragment {
.setTitle("Delete Pet") .setTitle("Delete Pet")
.setMessage("Are you sure you want to delete " + etPetName.getText().toString() + "?") .setMessage("Are you sure you want to delete " + etPetName.getText().toString() + "?")
.setPositiveButton("Delete", (dialog, which) -> { .setPositiveButton("Delete", (dialog, which) -> {
PetApi petApi = RetrofitClient.getPetApi(requireContext());
//if they say yes then delete the pet //if they say yes then delete the pet
petApi.deletePet((long) petId).enqueue(new Callback<Void>() { petApi.deletePet((long) petId).enqueue(new Callback<Void>() {
@Override @Override
@@ -242,4 +244,4 @@ public class PetDetailFragment extends Fragment {
spinnerPetStatus.setAdapter(adapter); spinnerPetStatus.setAdapter(adapter);
} }
} }

View File

@@ -29,11 +29,17 @@ import java.io.FileOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.*;
import javax.inject.Inject;
import javax.inject.Named;
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.*; import retrofit2.*;
@AndroidEntryPoint
public class ProductDetailFragment extends Fragment { public class ProductDetailFragment extends Fragment {
private TextView tvMode, tvProductId; private TextView tvMode, tvProductId;
@@ -50,6 +56,10 @@ public class ProductDetailFragment extends Fragment {
private List<CategoryDTO> categoryList = new ArrayList<>(); private List<CategoryDTO> categoryList = new ArrayList<>();
private Uri photoUri; private Uri photoUri;
@Inject ProductApi productApi;
@Inject CategoryApi categoryApi;
@Inject @Named("baseUrl") String baseUrl;
private ActivityResultLauncher<Intent> galleryLauncher; private ActivityResultLauncher<Intent> galleryLauncher;
private ActivityResultLauncher<Uri> cameraLauncher; private ActivityResultLauncher<Uri> cameraLauncher;
private ActivityResultLauncher<String> permissionLauncher; private ActivityResultLauncher<String> permissionLauncher;
@@ -155,7 +165,7 @@ public class ProductDetailFragment extends Fragment {
// Helper function to remove the photo // Helper function to remove the photo
private void removePhoto() { private void removePhoto() {
if (isEditing) { if (isEditing) {
RetrofitClient.getProductApi(requireContext()).deleteProductImage(prodId) productApi.deleteProductImage(prodId)
.enqueue(new Callback<Void>() { .enqueue(new Callback<Void>() {
@Override @Override
public void onResponse(Call<Void> call, Response<Void> response) { public void onResponse(Call<Void> call, Response<Void> response) {
@@ -187,7 +197,7 @@ public class ProductDetailFragment extends Fragment {
} }
private void loadCategories() { private void loadCategories() {
RetrofitClient.getCategoryApi(requireContext()).getAllCategories(0, 100) categoryApi.getAllCategories(0, 100)
.enqueue(new Callback<PageResponse<CategoryDTO>>() { .enqueue(new Callback<PageResponse<CategoryDTO>>() {
public void onResponse(Call<PageResponse<CategoryDTO>> c, public void onResponse(Call<PageResponse<CategoryDTO>> c,
Response<PageResponse<CategoryDTO>> r) { Response<PageResponse<CategoryDTO>> r) {
@@ -243,7 +253,7 @@ public class ProductDetailFragment extends Fragment {
//load the product image from the backend //load the product image from the backend
private void loadProductImage() { private void loadProductImage() {
String imageUrl = RetrofitClient.BASE_URL + String.format(Locale.US, ProductApi.PRODUCT_IMAGE_PATH, prodId); String imageUrl = baseUrl + String.format(Locale.US, ProductApi.PRODUCT_IMAGE_PATH, prodId);
Glide.with(this) Glide.with(this)
.load(imageUrl) .load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.NONE) .diskCacheStrategy(DiskCacheStrategy.NONE)
@@ -262,7 +272,7 @@ public class ProductDetailFragment extends Fragment {
RequestBody requestFile = RequestBody.create(file, MediaType.parse(requireContext().getContentResolver().getType(uri))); RequestBody requestFile = RequestBody.create(file, MediaType.parse(requireContext().getContentResolver().getType(uri)));
MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile); MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
RetrofitClient.getProductApi(requireContext()).uploadProductImage(prodId, body) productApi.uploadProductImage(prodId, body)
.enqueue(new Callback<Void>() { .enqueue(new Callback<Void>() {
@Override @Override
public void onResponse(Call<Void> call, Response<Void> response) { public void onResponse(Call<Void> call, Response<Void> response) {
@@ -328,11 +338,10 @@ public class ProductDetailFragment extends Fragment {
ProductDTO dto = new ProductDTO(name, category.getCategoryId(), desc, price); ProductDTO dto = new ProductDTO(name, category.getCategoryId(), desc, price);
ProductApi api = RetrofitClient.getProductApi(requireContext());
if (isEditing) { if (isEditing) {
api.updateProduct(prodId, dto).enqueue(simpleCallback("Updated")); productApi.updateProduct(prodId, dto).enqueue(simpleCallback("Updated"));
} else { } else {
api.createProduct(dto).enqueue(new Callback<ProductDTO>() { productApi.createProduct(dto).enqueue(new Callback<ProductDTO>() {
@Override @Override
public void onResponse(Call<ProductDTO> call, Response<ProductDTO> response) { public void onResponse(Call<ProductDTO> call, Response<ProductDTO> response) {
if (response.isSuccessful() && response.body() != null) { if (response.isSuccessful() && response.body() != null) {
@@ -375,8 +384,7 @@ public class ProductDetailFragment extends Fragment {
new AlertDialog.Builder(requireContext()) new AlertDialog.Builder(requireContext())
.setTitle("Delete Product?") .setTitle("Delete Product?")
.setPositiveButton("Yes", (d, w) -> .setPositiveButton("Yes", (d, w) ->
RetrofitClient.getProductApi(requireContext()) productApi.deleteProduct(prodId)
.deleteProduct(prodId)
.enqueue(new Callback<Void>() { .enqueue(new Callback<Void>() {
public void onResponse(Call<Void> c, Response<Void> r) { public void onResponse(Call<Void> c, Response<Void> r) {
navigateBack(); navigateBack();

View File

@@ -14,8 +14,13 @@ import com.example.petstoremobile.dtos.*;
import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.fragments.ListFragment;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.*;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.*; import retrofit2.*;
@AndroidEntryPoint
public class ProductSupplierDetailFragment extends Fragment { public class ProductSupplierDetailFragment extends Fragment {
private TextView tvMode; private TextView tvMode;
@@ -32,6 +37,10 @@ public class ProductSupplierDetailFragment extends Fragment {
private List<ProductDTO> productList = new ArrayList<>(); private List<ProductDTO> productList = new ArrayList<>();
private List<SupplierDTO> supplierList = new ArrayList<>(); private List<SupplierDTO> supplierList = new ArrayList<>();
@Inject ProductSupplierApi productSupplierApi;
@Inject ProductApi productApi;
@Inject SupplierApi supplierApi;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
@@ -62,7 +71,7 @@ public class ProductSupplierDetailFragment extends Fragment {
} }
private void loadProducts() { private void loadProducts() {
RetrofitClient.getProductApi(requireContext()).getAllProducts(null, 0, 200) productApi.getAllProducts(null, 0, 200)
.enqueue(new Callback<PageResponse<ProductDTO>>() { .enqueue(new Callback<PageResponse<ProductDTO>>() {
public void onResponse(Call<PageResponse<ProductDTO>> c, public void onResponse(Call<PageResponse<ProductDTO>> c,
Response<PageResponse<ProductDTO>> r) { Response<PageResponse<ProductDTO>> r) {
@@ -93,7 +102,7 @@ public class ProductSupplierDetailFragment extends Fragment {
} }
private void loadSuppliers() { private void loadSuppliers() {
RetrofitClient.getSupplierApi(requireContext()).getAllSuppliers(0, 200) supplierApi.getAllSuppliers(0, 200)
.enqueue(new Callback<PageResponse<SupplierDTO>>() { .enqueue(new Callback<PageResponse<SupplierDTO>>() {
public void onResponse(Call<PageResponse<SupplierDTO>> c, public void onResponse(Call<PageResponse<SupplierDTO>> c,
Response<PageResponse<SupplierDTO>> r) { Response<PageResponse<SupplierDTO>> r) {
@@ -164,12 +173,11 @@ public class ProductSupplierDetailFragment extends Fragment {
ProductSupplierDTO dto = new ProductSupplierDTO( ProductSupplierDTO dto = new ProductSupplierDTO(
product.getProdId(), supplier.getSupId(), cost); product.getProdId(), supplier.getSupId(), cost);
ProductSupplierApi api = RetrofitClient.getProductSupplierApi(requireContext());
if (isEditing) { if (isEditing) {
api.updateProductSupplier(editProductId, editSupplierId, dto) productSupplierApi.updateProductSupplier(editProductId, editSupplierId, dto)
.enqueue(simpleCallback("Updated")); .enqueue(simpleCallback("Updated"));
} else { } else {
api.createProductSupplier(dto).enqueue(simpleCallback("Saved")); productSupplierApi.createProductSupplier(dto).enqueue(simpleCallback("Saved"));
} }
} }
@@ -200,8 +208,7 @@ public class ProductSupplierDetailFragment extends Fragment {
new AlertDialog.Builder(requireContext()) new AlertDialog.Builder(requireContext())
.setTitle("Delete?") .setTitle("Delete?")
.setPositiveButton("Yes", (d, w) -> .setPositiveButton("Yes", (d, w) ->
RetrofitClient.getProductSupplierApi(requireContext()) productSupplierApi.deleteProductSupplier(editProductId, editSupplierId)
.deleteProductSupplier(editProductId, editSupplierId)
.enqueue(new Callback<Void>() { .enqueue(new Callback<Void>() {
public void onResponse(Call<Void> c, Response<Void> r) { public void onResponse(Call<Void> c, Response<Void> r) {
navigateBack(); navigateBack();

View File

@@ -9,6 +9,9 @@ import androidx.fragment.app.Fragment;
import com.example.petstoremobile.R; import com.example.petstoremobile.R;
import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.fragments.ListFragment;
import dagger.hilt.android.AndroidEntryPoint;
@AndroidEntryPoint
public class PurchaseOrderDetailFragment extends Fragment { public class PurchaseOrderDetailFragment extends Fragment {
private TextView tvId, tvSupplier, tvDate, tvStatus; private TextView tvId, tvSupplier, tvDate, tvStatus;

View File

@@ -13,11 +13,17 @@ 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.adapters.BlackTextArrayAdapter; import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
import com.example.petstoremobile.api.SaleApi;
import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.fragments.ListFragment;
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;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
@AndroidEntryPoint
public class RefundDetailFragment extends Fragment { public class RefundDetailFragment extends Fragment {
private EditText etRefundSaleId, etRefundReason; private EditText etRefundSaleId, etRefundReason;
@@ -27,6 +33,8 @@ public class RefundDetailFragment extends Fragment {
private int saleId; private int saleId;
private SaleFragment saleFragment; private SaleFragment saleFragment;
@Inject SaleApi saleApi;
public void setSaleFragment(SaleFragment fragment) { public void setSaleFragment(SaleFragment fragment) {
this.saleFragment = fragment; this.saleFragment = fragment;
} }

View File

@@ -15,7 +15,6 @@ 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.api.RetrofitClient;
import com.example.petstoremobile.api.ServiceApi; import com.example.petstoremobile.api.ServiceApi;
import com.example.petstoremobile.dtos.ServiceDTO; import com.example.petstoremobile.dtos.ServiceDTO;
import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.fragments.ListFragment;
@@ -23,10 +22,14 @@ import com.example.petstoremobile.fragments.listfragments.ServiceFragment;
import com.example.petstoremobile.utils.ActivityLogger; import com.example.petstoremobile.utils.ActivityLogger;
import com.example.petstoremobile.utils.InputValidator; import com.example.petstoremobile.utils.InputValidator;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@AndroidEntryPoint
public class ServiceDetailFragment extends Fragment { public class ServiceDetailFragment extends Fragment {
private TextView tvMode, tvServiceId; private TextView tvMode, tvServiceId;
@@ -36,6 +39,8 @@ public class ServiceDetailFragment extends Fragment {
private boolean isEditing = false; private boolean isEditing = false;
private ServiceFragment serviceFragment; private ServiceFragment serviceFragment;
@Inject ServiceApi serviceApi;
//set the service fragment to the parent so we refer back to service view when save or delete is done //set the service fragment to the parent so we refer back to service view when save or delete is done
public void setServiceFragment(ServiceFragment fragment) { public void setServiceFragment(ServiceFragment fragment) {
this.serviceFragment = fragment; this.serviceFragment = fragment;
@@ -79,8 +84,6 @@ public class ServiceDetailFragment extends Fragment {
serviceDTO.setServiceDuration(duration); serviceDTO.setServiceDuration(duration);
serviceDTO.setServicePrice(price); serviceDTO.setServicePrice(price);
ServiceApi serviceApi = RetrofitClient.getServiceApi(requireContext());
//check if the service is being edited or added //check if the service is being edited or added
if (isEditing) { if (isEditing) {
// Update existing service // Update existing service
@@ -135,7 +138,6 @@ public class ServiceDetailFragment extends Fragment {
.setTitle("Delete Service") .setTitle("Delete Service")
.setMessage("Are you sure you want to delete " + etServiceName.getText().toString() + "?") .setMessage("Are you sure you want to delete " + etServiceName.getText().toString() + "?")
.setPositiveButton("Delete", (dialog, which) -> { .setPositiveButton("Delete", (dialog, which) -> {
ServiceApi serviceApi = RetrofitClient.getServiceApi(requireContext());
serviceApi.deleteService((long) serviceId).enqueue(new Callback<Void>() { serviceApi.deleteService((long) serviceId).enqueue(new Callback<Void>() {
@Override @Override
public void onResponse(Call<Void> call, Response<Void> response) { public void onResponse(Call<Void> call, Response<Void> response) {
@@ -205,4 +207,4 @@ public class ServiceDetailFragment extends Fragment {
btnDeleteService = view.findViewById(R.id.btnDeleteService); btnDeleteService = view.findViewById(R.id.btnDeleteService);
btnBack = view.findViewById(R.id.btnBack); btnBack = view.findViewById(R.id.btnBack);
} }
} }

View File

@@ -15,7 +15,6 @@ 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.api.RetrofitClient;
import com.example.petstoremobile.api.SupplierApi; import com.example.petstoremobile.api.SupplierApi;
import com.example.petstoremobile.dtos.SupplierDTO; import com.example.petstoremobile.dtos.SupplierDTO;
import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.fragments.ListFragment;
@@ -23,10 +22,14 @@ import com.example.petstoremobile.fragments.listfragments.SupplierFragment;
import com.example.petstoremobile.utils.ActivityLogger; import com.example.petstoremobile.utils.ActivityLogger;
import com.example.petstoremobile.utils.InputValidator; import com.example.petstoremobile.utils.InputValidator;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@AndroidEntryPoint
public class SupplierDetailFragment extends Fragment { public class SupplierDetailFragment extends Fragment {
private TextView tvMode, tvSupId; private TextView tvMode, tvSupId;
@@ -36,6 +39,8 @@ public class SupplierDetailFragment extends Fragment {
private boolean isEditing = false; private boolean isEditing = false;
private SupplierFragment supplierFragment; private SupplierFragment supplierFragment;
@Inject SupplierApi supplierApi;
//set the supplier fragment to the parent so we refer back to supplier view when save or delete is done //set the supplier fragment to the parent so we refer back to supplier view when save or delete is done
public void setSupplierFragment(SupplierFragment fragment) { public void setSupplierFragment(SupplierFragment fragment) {
this.supplierFragment = fragment; this.supplierFragment = fragment;
@@ -82,8 +87,6 @@ public class SupplierDetailFragment extends Fragment {
supplierDTO.setSupEmail(email); supplierDTO.setSupEmail(email);
supplierDTO.setSupPhone(phone); supplierDTO.setSupPhone(phone);
SupplierApi supplierApi = RetrofitClient.getSupplierApi(requireContext());
//check if the supplier is being edited or added //check if the supplier is being edited or added
if (isEditing) { if (isEditing) {
// Update existing supplier // Update existing supplier
@@ -138,7 +141,6 @@ public class SupplierDetailFragment extends Fragment {
.setTitle("Delete Supplier") .setTitle("Delete Supplier")
.setMessage("Are you sure you want to delete " + etSupCompany.getText().toString() + "?") .setMessage("Are you sure you want to delete " + etSupCompany.getText().toString() + "?")
.setPositiveButton("Delete", (dialog, which) -> { .setPositiveButton("Delete", (dialog, which) -> {
SupplierApi supplierApi = RetrofitClient.getSupplierApi(requireContext());
supplierApi.deleteSupplier((long) supId).enqueue(new Callback<Void>() { supplierApi.deleteSupplier((long) supId).enqueue(new Callback<Void>() {
@Override @Override
public void onResponse(Call<Void> call, Response<Void> response) { public void onResponse(Call<Void> call, Response<Void> response) {
@@ -215,4 +217,4 @@ public class SupplierDetailFragment extends Fragment {
btnDeleteSupplier = view.findViewById(R.id.btnDeleteSupplier); btnDeleteSupplier = view.findViewById(R.id.btnDeleteSupplier);
btnBack = view.findViewById(R.id.btnBack); btnBack = view.findViewById(R.id.btnBack);
} }
} }

View File

@@ -29,7 +29,6 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.example.petstoremobile.R; import com.example.petstoremobile.R;
import com.example.petstoremobile.api.PetApi; import com.example.petstoremobile.api.PetApi;
import com.example.petstoremobile.api.RetrofitClient;
import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.fragments.ListFragment;
import com.example.petstoremobile.fragments.listfragments.detailfragments.PetDetailFragment; import com.example.petstoremobile.fragments.listfragments.detailfragments.PetDetailFragment;
@@ -40,6 +39,10 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import javax.inject.Inject;
import javax.inject.Named;
import dagger.hilt.android.AndroidEntryPoint;
import okhttp3.MediaType; import okhttp3.MediaType;
import okhttp3.MultipartBody; import okhttp3.MultipartBody;
import okhttp3.RequestBody; import okhttp3.RequestBody;
@@ -47,6 +50,7 @@ import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@AndroidEntryPoint
public class PetProfileFragment extends Fragment { public class PetProfileFragment extends Fragment {
private TextView tvPetName, tvPetSpecies, tvPetBreed, tvPetAge, tvPetPrice; private TextView tvPetName, tvPetSpecies, tvPetBreed, tvPetAge, tvPetPrice;
@@ -56,6 +60,9 @@ public class PetProfileFragment extends Fragment {
private int petId; private int petId;
private boolean hasImage = false; private boolean hasImage = false;
@Inject PetApi petApi;
@Inject @Named("baseUrl") String baseUrl;
// launchers for camera and gallery // launchers for camera and gallery
private ActivityResultLauncher<Intent> galleryLauncher; private ActivityResultLauncher<Intent> galleryLauncher;
private ActivityResultLauncher<Uri> cameraLauncher; private ActivityResultLauncher<Uri> cameraLauncher;
@@ -201,7 +208,7 @@ public class PetProfileFragment extends Fragment {
// Helper function to load pet image from backend // Helper function to load pet image from backend
private void loadPetImage(int petId) { private void loadPetImage(int petId) {
String imageUrl = RetrofitClient.BASE_URL + String.format(Locale.US, PetApi.PET_IMAGE_PATH, petId); String imageUrl = baseUrl + String.format(Locale.US, PetApi.PET_IMAGE_PATH, petId);
Glide.with(this) Glide.with(this)
.load(imageUrl) .load(imageUrl)
@@ -236,7 +243,6 @@ public class PetProfileFragment extends Fragment {
MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile); MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
// Call the backend to upload the image // Call the backend to upload the image
PetApi petApi = RetrofitClient.getPetApi(requireContext());
petApi.uploadPetImage((long) petId, body).enqueue(new Callback<Void>() { petApi.uploadPetImage((long) petId, body).enqueue(new Callback<Void>() {
@Override @Override
public void onResponse(Call<Void> call, Response<Void> response) { public void onResponse(Call<Void> call, Response<Void> response) {
@@ -261,7 +267,6 @@ public class PetProfileFragment extends Fragment {
} }
private void deletePetImage() { private void deletePetImage() {
PetApi petApi = RetrofitClient.getPetApi(requireContext());
petApi.deletePetImage((long) petId).enqueue(new Callback<Void>() { petApi.deletePetImage((long) petId).enqueue(new Callback<Void>() {
@Override @Override
public void onResponse(Call<Void> call, Response<Void> response) { public void onResponse(Call<Void> call, Response<Void> response) {

View File

@@ -8,7 +8,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
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.RetrofitClient;
import com.example.petstoremobile.api.auth.TokenManager; import com.example.petstoremobile.api.auth.TokenManager;
import com.example.petstoremobile.dtos.ConversationDTO; import com.example.petstoremobile.dtos.ConversationDTO;
import com.example.petstoremobile.dtos.CustomerDTO; import com.example.petstoremobile.dtos.CustomerDTO;
@@ -21,11 +20,17 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
// Service to receive notifications when a new conversation is created // Service to receive notifications when a new conversation is created
@AndroidEntryPoint
public class ChatNotificationService extends Service { public class ChatNotificationService extends Service {
private static final String TAG = "ChatNotificationService"; private static final String TAG = "ChatNotificationService";
@@ -37,6 +42,11 @@ public class ChatNotificationService extends Service {
private final Map<Long, String> customerIdToName = new HashMap<>(); private final Map<Long, String> customerIdToName = new HashMap<>();
private Long currentUserId; private Long currentUserId;
@Inject CustomerApi customerApi;
@Inject ChatApi chatApi;
@Inject TokenManager tokenManager;
@Inject @Named("baseUrl") String baseUrl;
//When the service starts, connect to the websocket //When the service starts, connect to the websocket
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
@@ -48,14 +58,11 @@ public class ChatNotificationService extends Service {
// helper function to connect to the websocket // helper function to connect to the websocket
private void connectWebSocket() { private void connectWebSocket() {
//get the token and role from the shared preferences //get the token and role from the shared preferences
TokenManager tm = TokenManager.getInstance(this); String token = tokenManager.getToken();
String token = tm.getToken(); String role = tokenManager.getRole();
String role = tm.getRole(); currentUserId = tokenManager.getUserId();
currentUserId = tm.getUserId();
if (token != null && stompChatManager == null) { if (token != null && stompChatManager == null) {
//load customers to have names associated with customer ids
CustomerApi customerApi = RetrofitClient.getCustomerApi(this);
customerApi.getAllCustomers(0, 1000).enqueue(new Callback<PageResponse<CustomerDTO>>() { customerApi.getAllCustomers(0, 1000).enqueue(new Callback<PageResponse<CustomerDTO>>() {
@Override @Override
public void onResponse(@NonNull Call<PageResponse<CustomerDTO>> call, @NonNull Response<PageResponse<CustomerDTO>> response) { public void onResponse(@NonNull Call<PageResponse<CustomerDTO>> call, @NonNull Response<PageResponse<CustomerDTO>> response) {
@@ -78,7 +85,6 @@ public class ChatNotificationService extends Service {
private void loadConversationsAndStartStomp(String token, String role) { private void loadConversationsAndStartStomp(String token, String role) {
// Fetch existing conversations // Fetch existing conversations
ChatApi chatApi = RetrofitClient.getChatApi(this);
chatApi.getAllConversations().enqueue(new Callback<List<ConversationDTO>>() { chatApi.getAllConversations().enqueue(new Callback<List<ConversationDTO>>() {
@Override @Override
public void onResponse(@NonNull Call<List<ConversationDTO>> call, @NonNull Response<List<ConversationDTO>> response) { public void onResponse(@NonNull Call<List<ConversationDTO>> call, @NonNull Response<List<ConversationDTO>> response) {
@@ -110,7 +116,7 @@ public class ChatNotificationService extends Service {
private void startStomp(String token, String role) { private void startStomp(String token, String role) {
if (stompChatManager != null) return; if (stompChatManager != null) return;
stompChatManager = new StompChatManager(token, role); stompChatManager = new StompChatManager(token, role, baseUrl);
// Listen for messages in existing conversations // Listen for messages in existing conversations
stompChatManager.setMessageListener(message -> { stompChatManager.setMessageListener(message -> {
@@ -193,7 +199,6 @@ public class ChatNotificationService extends Service {
// Helper function to fetch customer name for a conversation // Helper function to fetch customer name for a conversation
private void fetchCustomerName(Long customerId) { private void fetchCustomerName(Long customerId) {
CustomerApi customerApi = RetrofitClient.getCustomerApi(this);
customerApi.getCustomerById(customerId).enqueue(new Callback<CustomerDTO>() { customerApi.getCustomerById(customerId).enqueue(new Callback<CustomerDTO>() {
@Override @Override
public void onResponse(@NonNull Call<CustomerDTO> call, @NonNull Response<CustomerDTO> response) { public void onResponse(@NonNull Call<CustomerDTO> call, @NonNull Response<CustomerDTO> response) {
@@ -223,4 +228,4 @@ public class ChatNotificationService extends Service {
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
return null; return null;
} }
} }

View File

@@ -3,7 +3,6 @@ package com.example.petstoremobile.websocket;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.util.Log; import android.util.Log;
import com.example.petstoremobile.api.RetrofitClient;
import com.example.petstoremobile.dtos.ConversationDTO; import com.example.petstoremobile.dtos.ConversationDTO;
import com.example.petstoremobile.dtos.MessageDTO; import com.example.petstoremobile.dtos.MessageDTO;
import com.google.gson.Gson; import com.google.gson.Gson;
@@ -54,14 +53,16 @@ public class StompChatManager {
private ConnectionListener connectionListener; private ConnectionListener connectionListener;
private final String authToken; private final String authToken;
private final String role; private final String role;
private final String baseUrl;
private boolean isConnected; private boolean isConnected;
private boolean isConnecting; private boolean isConnecting;
private boolean manualDisconnect; private boolean manualDisconnect;
private Long pendingConversationId; private Long pendingConversationId;
public StompChatManager(String authToken, String role) { public StompChatManager(String authToken, String role, String baseUrl) {
this.authToken = authToken; this.authToken = authToken;
this.role = role == null ? "" : role.trim().toUpperCase(Locale.ROOT); this.role = role == null ? "" : role.trim().toUpperCase(Locale.ROOT);
this.baseUrl = baseUrl;
} }
public void setMessageListener(MessageListener listener) { public void setMessageListener(MessageListener listener) {
@@ -267,16 +268,16 @@ public class StompChatManager {
// Make the URL for the websocket connection // Make the URL for the websocket connection
private String buildWebSocketUrl() { private String buildWebSocketUrl() {
String baseUrl = RetrofitClient.BASE_URL.endsWith("/") String cleanBaseUrl = baseUrl.endsWith("/")
? RetrofitClient.BASE_URL.substring(0, RetrofitClient.BASE_URL.length() - 1) ? baseUrl.substring(0, baseUrl.length() - 1)
: RetrofitClient.BASE_URL; : baseUrl;
if (baseUrl.startsWith("https://")) { if (cleanBaseUrl.startsWith("https://")) {
return "wss://" + baseUrl.substring("https://".length()) + "/ws/chat"; return "wss://" + cleanBaseUrl.substring("https://".length()) + "/ws/chat";
} }
if (baseUrl.startsWith("http://")) { if (cleanBaseUrl.startsWith("http://")) {
return "ws://" + baseUrl.substring("http://".length()) + "/ws/chat"; return "ws://" + cleanBaseUrl.substring("http://".length()) + "/ws/chat";
} }
return baseUrl + "/ws/chat"; return cleanBaseUrl + "/ws/chat";
} }
// Helper to check if the current user is a customer // Helper to check if the current user is a customer
@@ -292,4 +293,4 @@ public class StompChatManager {
reconnectHandler.removeCallbacksAndMessages(null); reconnectHandler.removeCallbacksAndMessages(null);
reconnectHandler.postDelayed(this::connect, 1000); reconnectHandler.postDelayed(this::connect, 1000);
} }
} }

View File

@@ -1,4 +1,5 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { plugins {
alias(libs.plugins.android.application) apply false alias(libs.plugins.android.application) apply false
alias(libs.plugins.hilt) apply false
} }

View File

@@ -8,6 +8,7 @@ material = "1.13.0"
activity = "1.12.4" activity = "1.12.4"
constraintlayout = "2.2.1" constraintlayout = "2.2.1"
swiperefreshlayout = "1.2.0" swiperefreshlayout = "1.2.0"
hilt = "2.51.1"
[libraries] [libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" } junit = { group = "junit", name = "junit", version.ref = "junit" }
@@ -18,7 +19,9 @@ material = { group = "com.google.android.material", name = "material", version.r
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" } swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
[plugins] [plugins]
android-application = { id = "com.android.application", version.ref = "agp" } android-application = { id = "com.android.application", version.ref = "agp" }
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }