Merge branch 'master' into store
This commit is contained in:
@@ -37,6 +37,13 @@ dependencies {
|
||||
implementation(libs.activity)
|
||||
implementation(libs.constraintlayout)
|
||||
|
||||
|
||||
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
||||
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:4.9.1")
|
||||
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||
|
||||
|
||||
implementation("com.google.android.material:material:1.11.0")
|
||||
implementation("androidx.viewpager2:viewpager2:1.1.0")
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
@@ -13,6 +14,7 @@
|
||||
android:required="false" />
|
||||
|
||||
<application
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
@@ -23,7 +25,7 @@
|
||||
android:theme="@style/Theme.PetStoreMobile">
|
||||
<activity
|
||||
android:name=".activities.HomeActivity"
|
||||
android:windowSoftInputMode="adjustNothing"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".activities.MainActivity"
|
||||
|
||||
@@ -7,7 +7,9 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.core.view.WindowInsetsControllerCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.example.petstoremobile.R;
|
||||
@@ -38,7 +40,7 @@ public class HomeActivity extends AppCompatActivity {
|
||||
loadFragment(new ListFragment());
|
||||
bottomNav.setSelectedItemId(R.id.nav_list);
|
||||
|
||||
//when an item in the bar is selected, load the corresponding fragment //TODO REPLACE THIS WITH DRAWER MENU
|
||||
//when an item in the bar is selected, load the corresponding fragment
|
||||
bottomNav.setOnItemSelectedListener(item -> {
|
||||
|
||||
if (item.getItemId() == R.id.nav_list) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.example.petstoremobile.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
@@ -9,13 +10,21 @@ import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import com.example.petstoremobile.R;
|
||||
import com.example.petstoremobile.api.Auth.AuthApi;
|
||||
import com.example.petstoremobile.api.Auth.TokenManager;
|
||||
import com.example.petstoremobile.api.RetrofitClient;
|
||||
import com.example.petstoremobile.dtos.AuthDTO;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
//The login screen activity
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private EditText etUser;
|
||||
@@ -57,17 +66,47 @@ public class MainActivity extends AppCompatActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
//check if username and password are correct TODO: Replace with actual login
|
||||
if (username.equals("admin") && password.equals("admin")) {
|
||||
Intent intent = new Intent(this, HomeActivity.class);
|
||||
startActivity(intent);
|
||||
Toast.makeText(this, "Login successful", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
else {
|
||||
Toast.makeText(this, "Login failed", Toast.LENGTH_SHORT).show();
|
||||
tvLoginStatus.setText("Login failed");
|
||||
}
|
||||
AuthApi authApi = RetrofitClient.getAuthApi(this);
|
||||
|
||||
//Call login from api and get response
|
||||
authApi.login(new AuthDTO.LoginRequest(username,password)).enqueue(new Callback<AuthDTO.LoginResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<AuthDTO.LoginResponse> call, Response<AuthDTO.LoginResponse> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
//save login data in shared preferences
|
||||
TokenManager.getInstance(MainActivity.this).saveLoginData(
|
||||
response.body().getToken(),
|
||||
response.body().getUsername(),
|
||||
response.body().getRole()
|
||||
);
|
||||
//go to home activity after login
|
||||
Intent intent = new Intent(MainActivity.this, HomeActivity.class);
|
||||
startActivity(intent);
|
||||
Toast.makeText(MainActivity.this, "Login successful", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
} else {
|
||||
// Toast.makeText(MainActivity.this, "Login failed", Toast.LENGTH_SHORT).show();
|
||||
// tvLoginStatus.setText("Login failed");
|
||||
|
||||
try {
|
||||
String errorBody = response.errorBody().string();
|
||||
Log.e("LOGIN", "Code: " + response.code() + " Error: " + errorBody);
|
||||
} catch (Exception e) {
|
||||
Log.e("LOGIN", "Code: " + response.code());
|
||||
}
|
||||
Toast.makeText(MainActivity.this,
|
||||
"Login failed: " + response.code(),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
tvLoginStatus.setText("Login failed: " + response.code());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<AuthDTO.LoginResponse> call, Throwable t) {
|
||||
Toast.makeText(MainActivity.this, "Login failed", Toast.LENGTH_SHORT).show();
|
||||
tvLoginStatus.setText("Login failed");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.example.petstoremobile.api.Auth;
|
||||
|
||||
import com.example.petstoremobile.dtos.AuthDTO;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.POST;
|
||||
|
||||
//Api for logging in
|
||||
public interface AuthApi {
|
||||
@POST("v1/auth/login")
|
||||
Call<AuthDTO.LoginResponse> login(@Body AuthDTO.LoginRequest loginRequest);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.example.petstoremobile.api.Auth;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
//Used to get the token from the backend for authenticated api calls
|
||||
public class AuthInterceptor implements Interceptor {
|
||||
|
||||
private final TokenManager tokenManager;
|
||||
|
||||
public AuthInterceptor(Context context) {
|
||||
this.tokenManager = TokenManager.getInstance(context);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Response intercept(@NonNull Chain chain) throws IOException {
|
||||
String token = tokenManager.getToken();
|
||||
|
||||
//If we have a token then add it to the request
|
||||
if (token != null) {
|
||||
Request request = chain.request().newBuilder()
|
||||
.addHeader("Authorization", "Bearer " + token)
|
||||
.build();
|
||||
return chain.proceed(request);
|
||||
}
|
||||
|
||||
//If no token then just pass the request
|
||||
return chain.proceed(chain.request());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.example.petstoremobile.api.Auth;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
//Store login token in shared preferences
|
||||
public class TokenManager {
|
||||
private static final String TOKEN_KEY = "token";
|
||||
private static final String USERNAME_KEY = "username";
|
||||
private static final String ROLE_KEY = "role";
|
||||
private static final String PREFS_NAME = "auth_prefs";
|
||||
|
||||
private static TokenManager instance;
|
||||
private SharedPreferences prefs;
|
||||
|
||||
private TokenManager(Context context) {
|
||||
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
|
||||
public void saveLoginData(String token, String username, String role) {
|
||||
prefs.edit()
|
||||
.putString(TOKEN_KEY, token)
|
||||
.putString(USERNAME_KEY, username)
|
||||
.putString(ROLE_KEY, role)
|
||||
.apply();
|
||||
}
|
||||
|
||||
//Getters
|
||||
public String getToken() {
|
||||
return prefs.getString(TOKEN_KEY, null);
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return prefs.getString(USERNAME_KEY, null);
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return prefs.getString(ROLE_KEY, null);
|
||||
}
|
||||
|
||||
//Check if logged in
|
||||
public boolean isLoggedIn() {
|
||||
return getToken() != null;
|
||||
}
|
||||
|
||||
//Clear login data
|
||||
public void clearLoginData() {
|
||||
prefs.edit().clear().apply();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
39
app/src/main/java/com/example/petstoremobile/api/PetApi.java
Normal file
39
app/src/main/java/com/example/petstoremobile/api/PetApi.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.example.petstoremobile.api;
|
||||
|
||||
import com.example.petstoremobile.dtos.PageResponse;
|
||||
import com.example.petstoremobile.dtos.PetDTO;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.DELETE;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.PUT;
|
||||
import retrofit2.http.Path;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
public interface PetApi {
|
||||
// Get all pets
|
||||
@GET("v1/pets")
|
||||
Call<PageResponse<PetDTO>> getAllPets(
|
||||
@Query("page") int page,
|
||||
@Query("size") int size
|
||||
);
|
||||
|
||||
// Get pet by id
|
||||
@GET("v1/pets/{id}")
|
||||
Call<PetDTO> getPetById(@Path("id") Long id);
|
||||
|
||||
// Create pet
|
||||
@POST("v1/pets")
|
||||
Call<PetDTO> createPet(@Body PetDTO pet);
|
||||
|
||||
// Update pet
|
||||
@PUT("v1/pets/{id}")
|
||||
Call<PetDTO> updatePet(@Path("id") Long id, @Body PetDTO pet);
|
||||
|
||||
// Delete pet
|
||||
@DELETE("v1/pets/{id}")
|
||||
Call<Void> deletePet(@Path("id") Long id);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.example.petstoremobile.api;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.example.petstoremobile.api.Auth.AuthApi;
|
||||
import com.example.petstoremobile.api.Auth.AuthInterceptor;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
|
||||
public class RetrofitClient {
|
||||
//base URL
|
||||
public static final String BASE_URL = "http://10.0.2.2:8080/api/"; //for emulator testing change to computer ip if using hardware to test
|
||||
|
||||
|
||||
private static Retrofit retrofit = null;
|
||||
|
||||
public static Retrofit getClient(Context context) {
|
||||
//create an http logging using an interceptor
|
||||
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
|
||||
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
|
||||
OkHttpClient client = new OkHttpClient.Builder()
|
||||
.addInterceptor(interceptor)
|
||||
.addInterceptor(new AuthInterceptor(context))
|
||||
.build();
|
||||
|
||||
//build the retrofit object with all needed properties
|
||||
retrofit = new Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.addConverterFactory(GsonConverterFactory.create()) //JSON converter
|
||||
.client(client) //logging interceptor - OkHttpClient
|
||||
.build();
|
||||
|
||||
return retrofit;
|
||||
}
|
||||
|
||||
//associate the retrofit object with the API interface
|
||||
public static PetApi getPetApi(Context context) {
|
||||
return getClient(context).create(PetApi.class);
|
||||
}
|
||||
|
||||
public static ServiceApi getServiceApi(Context context) {
|
||||
return getClient(context).create(ServiceApi.class);
|
||||
}
|
||||
|
||||
public static SupplierApi getSupplierApi(Context context) {
|
||||
return getClient(context).create(SupplierApi.class);
|
||||
}
|
||||
|
||||
public static AuthApi getAuthApi(Context context) {
|
||||
return getClient(context).create(AuthApi.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.example.petstoremobile.api;
|
||||
|
||||
import com.example.petstoremobile.dtos.PageResponse;
|
||||
import com.example.petstoremobile.dtos.ServiceDTO;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.DELETE;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.PUT;
|
||||
import retrofit2.http.Path;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
public interface ServiceApi {
|
||||
// Get all services
|
||||
@GET("v1/services")
|
||||
Call<PageResponse<ServiceDTO>> getAllServices(
|
||||
@Query("page") int page,
|
||||
@Query("size") int size
|
||||
);
|
||||
|
||||
// Get service by id
|
||||
@GET("v1/services/{id}")
|
||||
Call<ServiceDTO> getServiceById(@Path("id") Long id);
|
||||
|
||||
// Create service
|
||||
@POST("v1/services")
|
||||
Call<ServiceDTO> createService(@Body ServiceDTO service);
|
||||
|
||||
// Update service
|
||||
@PUT("v1/services/{id}")
|
||||
Call<ServiceDTO> updateService(@Path("id") Long id, @Body ServiceDTO service);
|
||||
|
||||
// Delete service
|
||||
@DELETE("v1/services/{id}")
|
||||
Call<Void> deleteService(@Path("id") Long id);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.example.petstoremobile.api;
|
||||
|
||||
import com.example.petstoremobile.dtos.PageResponse;
|
||||
import com.example.petstoremobile.dtos.SupplierDTO;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.DELETE;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.PUT;
|
||||
import retrofit2.http.Path;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
public interface SupplierApi {
|
||||
// Get all suppliers
|
||||
@GET("v1/suppliers")
|
||||
Call<PageResponse<SupplierDTO>> getAllSuppliers(
|
||||
@Query("page") int page,
|
||||
@Query("size") int size
|
||||
);
|
||||
|
||||
// Get supplier by id
|
||||
@GET("v1/suppliers/{id}")
|
||||
Call<SupplierDTO> getSupplierById(@Path("id") Long id);
|
||||
|
||||
// Create supplier
|
||||
@POST("v1/suppliers")
|
||||
Call<SupplierDTO> createSupplier(@Body SupplierDTO supplier);
|
||||
|
||||
// Update supplier
|
||||
@PUT("v1/suppliers/{id}")
|
||||
Call<SupplierDTO> updateSupplier(@Path("id") Long id, @Body SupplierDTO supplier);
|
||||
|
||||
// Delete supplier
|
||||
@DELETE("v1/suppliers/{id}")
|
||||
Call<Void> deleteSupplier(@Path("id") Long id);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.example.petstoremobile.dtos;
|
||||
|
||||
//Used to send login data to the backend
|
||||
public class AuthDTO {
|
||||
public static class LoginRequest {
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
public LoginRequest(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getUsername() { return username; }
|
||||
public String getPassword() { return password; }
|
||||
}
|
||||
|
||||
//Used to receive login data from the backend
|
||||
public static class LoginResponse {
|
||||
private String token;
|
||||
private String username;
|
||||
private String role;
|
||||
|
||||
public String getToken() { return token; }
|
||||
public String getUsername() { return username; }
|
||||
public String getRole() { return role; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.example.petstoremobile.dtos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
//Used to get data from the API
|
||||
public class PageResponse<T> {
|
||||
private List<T> content;
|
||||
private int totalPages;
|
||||
private long totalElements;
|
||||
private int number;
|
||||
private int size;
|
||||
private boolean last;
|
||||
|
||||
public List<T> getContent() {
|
||||
return content;
|
||||
}
|
||||
public int getTotalPages() {
|
||||
return totalPages;
|
||||
}
|
||||
public long getTotalElements() {
|
||||
return totalElements;
|
||||
}
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
public boolean isLast() {
|
||||
return last;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.example.petstoremobile.dtos;
|
||||
|
||||
public class PetDTO {
|
||||
private Long petId;
|
||||
private String petName;
|
||||
private String petSpecies;
|
||||
private String petBreed;
|
||||
private Integer petAge;
|
||||
private String petStatus;
|
||||
private String petPrice;
|
||||
private String createdAt;
|
||||
private String updatedAt;
|
||||
|
||||
public Long getPetId() { return petId; }
|
||||
public String getPetName() { return petName; }
|
||||
public String getPetSpecies() { return petSpecies; }
|
||||
public String getPetBreed() { return petBreed; }
|
||||
public Integer getPetAge() { return petAge; }
|
||||
public String getPetStatus() { return petStatus; }
|
||||
public String getPetPrice() { return petPrice; }
|
||||
public String getCreatedAt() { return createdAt; }
|
||||
public String getUpdatedAt() { return updatedAt; }
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.example.petstoremobile.dtos;
|
||||
|
||||
public class ServiceDTO {
|
||||
private Long serviceId;
|
||||
private String serviceName;
|
||||
private String serviceDesc;
|
||||
private Integer serviceDuration;
|
||||
private Double servicePrice;
|
||||
private String createdAt;
|
||||
private String updatedAt;
|
||||
|
||||
public Long getServiceId() { return serviceId; }
|
||||
public String getServiceName() { return serviceName; }
|
||||
public String getServiceDesc() { return serviceDesc; }
|
||||
public Integer getServiceDuration() { return serviceDuration; }
|
||||
public Double getServicePrice() { return servicePrice; }
|
||||
public String getCreatedAt() { return createdAt; }
|
||||
public String getUpdatedAt() { return updatedAt; }
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.example.petstoremobile.dtos;
|
||||
|
||||
public class SupplierDTO {
|
||||
private Long supId;
|
||||
private String supCompany;
|
||||
private String supContactFirstName;
|
||||
private String supContactLastName;
|
||||
private String supEmail;
|
||||
private String supPhone;
|
||||
private String createdAt;
|
||||
private String updatedAt;
|
||||
|
||||
public Long getSupId() { return supId; }
|
||||
public String getSupCompany() { return supCompany; }
|
||||
public String getSupContactFirstName() { return supContactFirstName; }
|
||||
public String getSupContactLastName() { return supContactLastName; }
|
||||
public String getSupEmail() { return supEmail; }
|
||||
public String getSupPhone() { return supPhone; }
|
||||
public String getCreatedAt() { return createdAt; }
|
||||
public String getUpdatedAt() { return updatedAt; }
|
||||
}
|
||||
@@ -6,26 +6,37 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.example.petstoremobile.R;
|
||||
import com.example.petstoremobile.adapters.PetAdapter;
|
||||
import com.example.petstoremobile.api.PetApi;
|
||||
import com.example.petstoremobile.api.RetrofitClient;
|
||||
import com.example.petstoremobile.dtos.PageResponse;
|
||||
import com.example.petstoremobile.dtos.PetDTO;
|
||||
import com.example.petstoremobile.fragments.ListFragment;
|
||||
import com.example.petstoremobile.fragments.listfragments.detailfragments.PetDetailFragment;
|
||||
import com.example.petstoremobile.fragments.listfragments.listprofilefragments.PetProfileFragment;
|
||||
import com.example.petstoremobile.models.Pet;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PetFragment extends Fragment implements PetAdapter.OnPetClickListener {
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class PetFragment extends Fragment implements PetAdapter.OnPetClickListener {
|
||||
private List<Pet> petList = new ArrayList<>();
|
||||
private PetAdapter adapter;
|
||||
private ImageButton hamburger;
|
||||
private PetAdapter adapter;
|
||||
private PetApi api;
|
||||
|
||||
//load pet view
|
||||
@Override
|
||||
@@ -33,10 +44,14 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_pet, container, false);
|
||||
|
||||
//get retrofit
|
||||
api = RetrofitClient.getPetApi(requireContext());
|
||||
|
||||
hamburger = view.findViewById(R.id.btnHamburger);
|
||||
|
||||
loadPetData(); //TODO: Replace this with actual data when backend is working
|
||||
setupRecyclerView(view);
|
||||
loadPetData(); //TODO: Replace this with actual data when backend is working
|
||||
|
||||
|
||||
//Add button to opens the add dialog
|
||||
FloatingActionButton fabAddPet = view.findViewById(R.id.fabAddPet);
|
||||
@@ -54,31 +69,35 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
||||
return view;
|
||||
}
|
||||
|
||||
//Open the pet detail view depending on the mode
|
||||
//Open pet profile
|
||||
private void openPetProfile(int position) {
|
||||
PetProfileFragment profileFragment = new PetProfileFragment();
|
||||
|
||||
//Make a bundle to pass data to the profile fragment
|
||||
Bundle args = new Bundle();
|
||||
Pet pet = petList.get(position);
|
||||
args.putInt("petId", pet.getPetId());
|
||||
args.putString("petName", pet.getPetName());
|
||||
args.putString("petSpecies", pet.getPetSpecies());
|
||||
args.putString("petBreed", pet.getPetBreed());
|
||||
args.putInt("petAge", pet.getPetAge());
|
||||
args.putString("petStatus", pet.getPetStatus());
|
||||
args.putDouble("petPrice", pet.getPetPrice());
|
||||
|
||||
//send the bundle to the profile fragment to display
|
||||
profileFragment.setArguments(args);
|
||||
|
||||
//get ListFragment to load the the pet profile view
|
||||
ListFragment listFragment = (ListFragment) getParentFragment();
|
||||
if (profileFragment != null) {
|
||||
listFragment.loadFragment(profileFragment);
|
||||
}
|
||||
}
|
||||
|
||||
//Open the pet detail view for adding
|
||||
private void openPetDetails(int position) {
|
||||
PetDetailFragment detailFragment = new PetDetailFragment();
|
||||
|
||||
//Make a bundle to pass data to the detail fragment
|
||||
Bundle args = new Bundle();
|
||||
args.putInt("position", position);
|
||||
|
||||
//if editing a pet, add the pet data to the bundle
|
||||
if (position != -1) {
|
||||
Pet pet = petList.get(position);
|
||||
args.putInt("petId", pet.getPetId());
|
||||
args.putString("petName", pet.getPetName());
|
||||
args.putString("petSpecies", pet.getPetSpecies());
|
||||
args.putString("petBreed", pet.getPetBreed());
|
||||
args.putInt("petAge", pet.getPetAge());
|
||||
args.putString("petStatus", pet.getPetStatus());
|
||||
args.putDouble("petPrice", pet.getPetPrice());
|
||||
}
|
||||
|
||||
//send the bundle to the detail fragment to display
|
||||
detailFragment.setArguments(args);
|
||||
//set the pet fragment to the parent so we refer back to pet view when save or delete is done
|
||||
detailFragment.setPetFragment(this);
|
||||
|
||||
//get ListFragment to load the the detail view
|
||||
ListFragment listFragment = (ListFragment) getParentFragment();
|
||||
if (listFragment != null) {
|
||||
@@ -87,36 +106,57 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
||||
}
|
||||
|
||||
// Called by PetDetailFragment when save or delete is done
|
||||
public void onPetSaved(int position, Pet pet) {
|
||||
if (position == -1) {
|
||||
petList.add(pet);
|
||||
adapter.notifyItemInserted(petList.size() - 1);
|
||||
} else {
|
||||
petList.set(position, pet);
|
||||
adapter.notifyItemChanged(position);
|
||||
}
|
||||
}
|
||||
|
||||
public void onPetDeleted(int position) {
|
||||
petList.remove(position);
|
||||
adapter.notifyItemRemoved(position);
|
||||
}
|
||||
//TODO: REPLACE THIS WITH JUST RELOADING THE LIST BY FETCHING FROM THE BACKEND
|
||||
// public void onPetSaved(int position, Pet pet) {
|
||||
// if (position == -1) {
|
||||
// petList.add(pet);
|
||||
// adapter.notifyItemInserted(petList.size() - 1);
|
||||
// } else {
|
||||
// petList.set(position, pet);
|
||||
// adapter.notifyItemChanged(position);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void onPetDeleted(int position) {
|
||||
// petList.remove(position);
|
||||
// adapter.notifyItemRemoved(position);
|
||||
// }
|
||||
|
||||
// Called by PetAdapter when a row is clicked to open the details view
|
||||
@Override
|
||||
public void onPetClick(int position) {
|
||||
openPetDetails(position);
|
||||
openPetProfile(position);
|
||||
}
|
||||
|
||||
// Helper function to get a list of all pets (Loads hardcoded sample data for now) TODO: REPLACE THIS WITH A METHOD THAT GETS DATA FROM THE DATABASE
|
||||
// Helper function to get a list of all pets from the backend
|
||||
private void loadPetData() {
|
||||
petList.clear();
|
||||
petList.add(new Pet(1, "Buddy","Dog", "Labrador",2, "Available", 500.00));
|
||||
petList.add(new Pet(2, "Milo", "Cat", "Persian",1, "Available", 300.00));
|
||||
petList.add(new Pet(3, "Charlie","Dog", "Golden Retriever", 3, "Available", 550.00));
|
||||
petList.add(new Pet(4, "Luna", "Cat", "Siamese",2, "Adopted", 350.00));
|
||||
petList.add(new Pet(5, "Max", "Dog", "Beagle",1, "Available", 450.00));
|
||||
petList.add(new Pet(6, "Bella", "Cat", "Maine Coon",4, "Available", 400.00));
|
||||
api.getAllPets(0, 100).enqueue(new Callback<PageResponse<PetDTO>>() {
|
||||
@Override
|
||||
public void onResponse(Call<PageResponse<PetDTO>> call, Response<PageResponse<PetDTO>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
petList.clear();
|
||||
|
||||
// Convert to pets
|
||||
List<Pet> pets = response.body().getContent()
|
||||
.stream()
|
||||
.map(Pet::new)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
petList.addAll(pets);
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
} else {
|
||||
Log.e("onResponse: ", response.message());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<PageResponse<PetDTO>> call, Throwable t) { // 4. here
|
||||
Toast.makeText(getContext(),
|
||||
"Failed to load pets", Toast.LENGTH_SHORT).show();
|
||||
Log.e("onFailure: ", t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//set up the recyclerview and adapter
|
||||
|
||||
@@ -6,13 +6,19 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.example.petstoremobile.R;
|
||||
import com.example.petstoremobile.adapters.ServiceAdapter;
|
||||
import com.example.petstoremobile.api.RetrofitClient;
|
||||
import com.example.petstoremobile.api.ServiceApi;
|
||||
import com.example.petstoremobile.dtos.PageResponse;
|
||||
import com.example.petstoremobile.dtos.ServiceDTO;
|
||||
import com.example.petstoremobile.fragments.ListFragment;
|
||||
import com.example.petstoremobile.fragments.listfragments.detailfragments.ServiceDetailFragment;
|
||||
import com.example.petstoremobile.models.Service;
|
||||
@@ -21,11 +27,16 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class ServiceFragment extends Fragment implements ServiceAdapter.OnServiceClickListener {
|
||||
|
||||
private List<Service> serviceList = new ArrayList<>();
|
||||
private ServiceAdapter adapter;
|
||||
private ImageButton hamburger;
|
||||
private ServiceApi api;
|
||||
|
||||
//load service view
|
||||
@Override
|
||||
@@ -33,10 +44,11 @@ public class ServiceFragment extends Fragment implements ServiceAdapter.OnServic
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_service, container, false);
|
||||
|
||||
api = RetrofitClient.getServiceApi(requireContext());
|
||||
hamburger = view.findViewById(R.id.btnHamburger);
|
||||
|
||||
loadServiceData(); //TODO: Replace this with actual data when backend is working
|
||||
setupRecyclerView(view);
|
||||
loadServiceData();
|
||||
|
||||
//Add button to opens the add dialog
|
||||
FloatingActionButton fabAddService = view.findViewById(R.id.fabAddService);
|
||||
@@ -106,14 +118,37 @@ public class ServiceFragment extends Fragment implements ServiceAdapter.OnServic
|
||||
openServiceDetails(position);
|
||||
}
|
||||
|
||||
// Helper function to get a list of all services (Loads hardcoded sample data for now) TODO: REPLACE THIS WITH A METHOD THAT GETS DATA FROM THE DATABASE
|
||||
// Helper function to get a list of all services from the backend
|
||||
private void loadServiceData() {
|
||||
serviceList.clear();
|
||||
serviceList.add(new Service(1, "Grooming", "Full grooming for your pet", 60, 50.00));
|
||||
serviceList.add(new Service(2, "Vaccination", "Standard vaccinations", 30, 75.00));
|
||||
serviceList.add(new Service(3, "Health Checkup", "Comprehensive health exam", 45, 100.00));
|
||||
serviceList.add(new Service(4, "Pet Sitting", "Overnight stay for your pet", 1440, 40.00));
|
||||
serviceList.add(new Service(5, "Training", "Basic obedience training session", 60, 60.00));
|
||||
api.getAllServices(0, 100).enqueue(new Callback<PageResponse<ServiceDTO>>() {
|
||||
@Override
|
||||
public void onResponse(Call<PageResponse<ServiceDTO>> call, Response<PageResponse<ServiceDTO>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
serviceList.clear();
|
||||
|
||||
// Convert to services
|
||||
List<Service> services = response.body().getContent()
|
||||
.stream()
|
||||
.map(Service::new)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
serviceList.addAll(services);
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
} else {
|
||||
Log.e("onResponse: ", response.message());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<PageResponse<ServiceDTO>> call, Throwable t) {
|
||||
if (getContext() != null) {
|
||||
Toast.makeText(getContext(),
|
||||
"Failed to load services", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
Log.e("onFailure: ", t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//set up the recyclerview and adapter
|
||||
|
||||
@@ -6,13 +6,19 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.example.petstoremobile.R;
|
||||
import com.example.petstoremobile.adapters.SupplierAdapter;
|
||||
import com.example.petstoremobile.api.RetrofitClient;
|
||||
import com.example.petstoremobile.api.SupplierApi;
|
||||
import com.example.petstoremobile.dtos.PageResponse;
|
||||
import com.example.petstoremobile.dtos.SupplierDTO;
|
||||
import com.example.petstoremobile.fragments.ListFragment;
|
||||
import com.example.petstoremobile.fragments.listfragments.detailfragments.SupplierDetailFragment;
|
||||
import com.example.petstoremobile.models.Supplier;
|
||||
@@ -21,11 +27,16 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupplierClickListener {
|
||||
|
||||
private List<Supplier> supplierList = new ArrayList<>();
|
||||
private SupplierAdapter adapter;
|
||||
private ImageButton hamburger;
|
||||
private SupplierApi api;
|
||||
|
||||
//load supplier view
|
||||
@Override
|
||||
@@ -33,10 +44,11 @@ public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupp
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_supplier, container, false);
|
||||
|
||||
api = RetrofitClient.getSupplierApi(requireContext());
|
||||
hamburger = view.findViewById(R.id.btnHamburger);
|
||||
|
||||
loadSupplierData(); //TODO: Replace this with actual data when backend is working
|
||||
setupRecyclerView(view);
|
||||
loadSupplierData();
|
||||
|
||||
//Add button to opens the add dialog
|
||||
FloatingActionButton fabAddSupplier = view.findViewById(R.id.fabAddSupplier);
|
||||
@@ -107,14 +119,37 @@ public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupp
|
||||
openSupplierDetails(position);
|
||||
}
|
||||
|
||||
// Helper function to get a list of all suppliers (Loads hardcoded sample data for now) TODO: REPLACE THIS WITH A METHOD THAT GETS DATA FROM THE DATABASE
|
||||
// Helper function to get a list of all suppliers from the backend
|
||||
private void loadSupplierData() {
|
||||
supplierList.clear();
|
||||
supplierList.add(new Supplier(1, "Pet Food Co.", "John", "Doe", "john@petfood.com", "123-456-7890"));
|
||||
supplierList.add(new Supplier(2, "Toy Kingdom", "Jane", "Smith", "jane@toykingdom.com", "987-654-3210"));
|
||||
supplierList.add(new Supplier(3, "HealthPet", "Robert", "Brown", "robert@healthpet.com", "555-0199-234"));
|
||||
supplierList.add(new Supplier(4, "Groomers Choice", "Emily", "Davis", "emily@groomers.com", "444-555-6666"));
|
||||
supplierList.add(new Supplier(5, "Birdy Haven", "Michael", "Wilson", "michael@birdyhaven.com", "111-222-3333"));
|
||||
api.getAllSuppliers(0, 100).enqueue(new Callback<PageResponse<SupplierDTO>>() {
|
||||
@Override
|
||||
public void onResponse(Call<PageResponse<SupplierDTO>> call, Response<PageResponse<SupplierDTO>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
supplierList.clear();
|
||||
|
||||
// Convert to suppliers
|
||||
List<Supplier> suppliers = response.body().getContent()
|
||||
.stream()
|
||||
.map(Supplier::new)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
supplierList.addAll(suppliers);
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
} else {
|
||||
Log.e("onResponse: ", response.message());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<PageResponse<SupplierDTO>> call, Throwable t) {
|
||||
if (getContext() != null) {
|
||||
Toast.makeText(getContext(),
|
||||
"Failed to load suppliers", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
Log.e("onFailure: ", t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//set up the recyclerview and adapter
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package com.example.petstoremobile.fragments.listfragments.listprofilefragments;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import android.provider.MediaStore;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.example.petstoremobile.R;
|
||||
import com.example.petstoremobile.fragments.ListFragment;
|
||||
import com.example.petstoremobile.fragments.listfragments.detailfragments.PetDetailFragment;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
|
||||
public class PetProfileFragment extends Fragment {
|
||||
|
||||
private TextView tvPetName, tvPetSpecies, tvPetBreed, tvPetAge, tvPetPrice;
|
||||
private Button btnBack, btnEditPet, btnChangePhoto;
|
||||
private ImageView imgPet;
|
||||
private Uri photoUri;
|
||||
|
||||
// launchers for camera and gallery
|
||||
private ActivityResultLauncher<Intent> galleryLauncher;
|
||||
private ActivityResultLauncher<Uri> cameraLauncher;
|
||||
private ActivityResultLauncher<String> permissionLauncher;
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Launcher to open gallery to select image
|
||||
galleryLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
result -> {
|
||||
if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) {
|
||||
Uri selectedImage = result.getData().getData();
|
||||
imgPet.setImageURI(selectedImage);
|
||||
// TODO: SAVE CHANGED PHOTO TO DATABASE
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Launcher for camera to open and capture image
|
||||
cameraLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.TakePicture(),
|
||||
success -> {
|
||||
if (success) {
|
||||
imgPet.setImageURI(null);
|
||||
imgPet.setImageURI(photoUri);
|
||||
// TODO: SAVE CHANGED PHOTO TO DATABASE
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Launcher to request camera permission
|
||||
permissionLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.RequestPermission(),
|
||||
granted -> {
|
||||
if (granted) {
|
||||
launchCamera();
|
||||
} else {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle("Permission Required")
|
||||
.setMessage("Please grant camera permission to use this feature")
|
||||
.setPositiveButton("Open Settings", (dialog, which) -> {
|
||||
Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
intent.setData(Uri.fromParts("package", requireContext().getPackageName(), null));
|
||||
startActivity(intent);
|
||||
})
|
||||
.setNegativeButton("Cancel", null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_pet_profile, container, false);
|
||||
|
||||
// Initialize views
|
||||
tvPetName = view.findViewById(R.id.tvPetName);
|
||||
tvPetSpecies = view.findViewById(R.id.tvPetSpecies);
|
||||
tvPetBreed = view.findViewById(R.id.tvPetBreed);
|
||||
tvPetAge = view.findViewById(R.id.tvPetAge);
|
||||
tvPetPrice = view.findViewById(R.id.tvPetPrice);
|
||||
btnBack = view.findViewById(R.id.btnBack);
|
||||
btnEditPet = view.findViewById(R.id.btnEditPet);
|
||||
btnChangePhoto = view.findViewById(R.id.btnChangePhoto);
|
||||
imgPet = view.findViewById(R.id.imgPet);
|
||||
|
||||
|
||||
// Set pet details to display
|
||||
if (getArguments() != null) {
|
||||
tvPetName.setText(getArguments().getString("petName"));
|
||||
tvPetSpecies.setText(getArguments().getString("petSpecies"));
|
||||
tvPetBreed.setText(getArguments().getString("petBreed"));
|
||||
tvPetAge.setText(String.format(Locale.getDefault(), "%d yr(s)", getArguments().getInt("petAge")));
|
||||
tvPetPrice.setText(String.format(Locale.getDefault(), "$%.2f", getArguments().getDouble("petPrice")));
|
||||
}
|
||||
|
||||
//set button click listeners
|
||||
btnBack.setOnClickListener(v -> {
|
||||
//get the list fragment and pop the back stack to return to the previous view (PetFragment)
|
||||
ListFragment listFragment = (ListFragment) getParentFragment();
|
||||
if (listFragment != null) {
|
||||
listFragment.getChildFragmentManager().popBackStack();
|
||||
}
|
||||
});
|
||||
|
||||
//Make the edit button go to the pet detail view
|
||||
btnEditPet.setOnClickListener(v -> {
|
||||
if (getArguments() == null) return;
|
||||
|
||||
PetDetailFragment detailFragment = new PetDetailFragment();
|
||||
//send the bundle to the pet detail fragment
|
||||
detailFragment.setArguments(getArguments());
|
||||
|
||||
//get ListFragment to load the the detail view
|
||||
ListFragment listFragment = (ListFragment) getParentFragment();
|
||||
if (listFragment != null) {
|
||||
listFragment.loadFragment(detailFragment);
|
||||
}
|
||||
});
|
||||
|
||||
//Make change photo button ask user to select a new photo
|
||||
btnChangePhoto.setOnClickListener(v -> {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle("Change Pet Photo")
|
||||
.setItems(new String[]{"Take Photo", "Choose from Gallery"}, (dialog, which) -> {
|
||||
if (which == 0) {
|
||||
// Choose Camera
|
||||
//Checks if the user has granted the camera permission already
|
||||
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
|
||||
//if the permission is already granted then launch the camera
|
||||
launchCamera();
|
||||
} else {
|
||||
//otherwise request the permission
|
||||
permissionLauncher.launch(Manifest.permission.CAMERA);
|
||||
}
|
||||
} else {
|
||||
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||
galleryLauncher.launch(intent);
|
||||
}
|
||||
})
|
||||
.show();
|
||||
});
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void launchCamera() {
|
||||
File photoFile = new File(requireContext().getCacheDir(), "pet_photo.jpg");
|
||||
photoUri = FileProvider.getUriForFile(requireContext(), requireContext().getPackageName() + ".fileprovider", photoFile);
|
||||
cameraLauncher.launch(photoUri);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.example.petstoremobile.models;
|
||||
|
||||
import com.example.petstoremobile.dtos.PetDTO;
|
||||
|
||||
public class Pet {
|
||||
private int petId;
|
||||
private String petName;
|
||||
@@ -20,6 +22,17 @@ public class Pet {
|
||||
this.petPrice = petPrice;
|
||||
}
|
||||
|
||||
//contructor to convert PetDTO to Pet
|
||||
public Pet(PetDTO dto) {
|
||||
this.petId = dto.getPetId().intValue();
|
||||
this.petName = dto.getPetName();
|
||||
this.petSpecies = dto.getPetSpecies();
|
||||
this.petBreed = dto.getPetBreed();
|
||||
this.petAge = dto.getPetAge();
|
||||
this.petStatus = dto.getPetStatus();
|
||||
this.petPrice = Double.parseDouble(dto.getPetPrice());
|
||||
}
|
||||
|
||||
//getter and setters
|
||||
public int getPetId() {
|
||||
return petId;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.example.petstoremobile.models;
|
||||
|
||||
import com.example.petstoremobile.dtos.ServiceDTO;
|
||||
|
||||
public class Service {
|
||||
private int serviceId;
|
||||
private String serviceName;
|
||||
@@ -16,15 +18,19 @@ public class Service {
|
||||
this.servicePrice = servicePrice;
|
||||
}
|
||||
|
||||
public Service(ServiceDTO dto) {
|
||||
this.serviceId = dto.getServiceId().intValue();
|
||||
this.serviceName = dto.getServiceName();
|
||||
this.serviceDesc = dto.getServiceDesc();
|
||||
this.serviceDuration = dto.getServiceDuration();
|
||||
this.servicePrice = dto.getServicePrice();
|
||||
}
|
||||
|
||||
//getter and setters
|
||||
public int getServiceId() {
|
||||
return serviceId;
|
||||
}
|
||||
|
||||
// public void setServiceId(int serviceId) {
|
||||
// this.serviceId = serviceId;
|
||||
// }
|
||||
|
||||
public String getServiceName() {
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.example.petstoremobile.models;
|
||||
|
||||
import com.example.petstoremobile.dtos.SupplierDTO;
|
||||
|
||||
public class Supplier {
|
||||
private int supId;
|
||||
private String supCompany;
|
||||
@@ -18,16 +20,21 @@ public class Supplier {
|
||||
this.supPhone = supPhone;
|
||||
}
|
||||
|
||||
public Supplier(SupplierDTO dto) {
|
||||
this.supId = dto.getSupId().intValue();
|
||||
this.supCompany = dto.getSupCompany();
|
||||
this.supContactFirstName = dto.getSupContactFirstName();
|
||||
this.supContactLastName = dto.getSupContactLastName();
|
||||
this.supEmail = dto.getSupEmail();
|
||||
this.supPhone = dto.getSupPhone();
|
||||
}
|
||||
|
||||
//getter and setters
|
||||
|
||||
public int getSupId() {
|
||||
return supId;
|
||||
}
|
||||
|
||||
// public void setSupId(int supId) {
|
||||
// this.supId = supId;
|
||||
// }
|
||||
|
||||
public String getSupCompany() {
|
||||
return supCompany;
|
||||
}
|
||||
|
||||
244
app/src/main/res/layout/fragment_pet_profile.xml
Normal file
244
app/src/main/res/layout/fragment_pet_profile.xml
Normal file
@@ -0,0 +1,244 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background_grey">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/primary_dark">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Pet Profile"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnEditPet"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Edit"
|
||||
android:backgroundTint="@color/accent_coral"
|
||||
android:textColor="@color/white"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgPet"
|
||||
android:layout_width="146dp"
|
||||
android:layout_height="140dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:background="@drawable/circle_image"
|
||||
android:clipToOutline="true"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/placeholder" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnChangePhoto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Change Photo"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:textColor="@color/text_light"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPetName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="NAME"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="26sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="@color/white"
|
||||
android:layout_marginEnd="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SPECIES"
|
||||
android:textSize="11sp"
|
||||
android:textColor="#888888"
|
||||
android:textAllCaps="true"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPetSpecies"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Dog"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_dark"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="@color/white"
|
||||
android:layout_marginStart="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="BREED"
|
||||
android:textSize="11sp"
|
||||
android:textColor="#888888"
|
||||
android:textAllCaps="true"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPetBreed"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Labrador"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_dark"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="@color/white"
|
||||
android:layout_marginEnd="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="AGE"
|
||||
android:textSize="11sp"
|
||||
android:textColor="#888888"
|
||||
android:textAllCaps="true"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPetAge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="2 yr(s)"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_dark"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="@color/white"
|
||||
android:layout_marginStart="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="PRICE"
|
||||
android:textSize="11sp"
|
||||
android:textColor="#888888"
|
||||
android:textAllCaps="true"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPetPrice"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="$500.00"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/accent_coral"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnBack"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Back"
|
||||
android:backgroundTint="@color/primary_medium"
|
||||
android:textColor="@color/white"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
8
app/src/main/res/xml/network_security_config.xml
Normal file
8
app/src/main/res/xml/network_security_config.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
||||
Reference in New Issue
Block a user