Funcionamiento compelto de las clases profile y de anime y manga donde se añade y se borran sin ningun problema!

This commit is contained in:
santi 2025-05-21 17:16:38 +02:00
parent 6b2d0c09ce
commit a5f1189cb5
13 changed files with 170 additions and 89 deletions

Binary file not shown.

View File

@ -5,6 +5,7 @@ import com.santiparra.yomitrack.db.entities.MangaEntity;
import com.santiparra.yomitrack.db.entities.UserEntity; import com.santiparra.yomitrack.db.entities.UserEntity;
import com.santiparra.yomitrack.model.AniListMedia; import com.santiparra.yomitrack.model.AniListMedia;
import com.santiparra.yomitrack.model.AnimePageResponse; import com.santiparra.yomitrack.model.AnimePageResponse;
import com.santiparra.yomitrack.model.ApiResponse;
import com.santiparra.yomitrack.model.LoginResponse; import com.santiparra.yomitrack.model.LoginResponse;
import com.santiparra.yomitrack.model.MangaPageResponse; import com.santiparra.yomitrack.model.MangaPageResponse;
import com.santiparra.yomitrack.model.RegisterResponse; import com.santiparra.yomitrack.model.RegisterResponse;
@ -49,10 +50,10 @@ public interface ApiService {
); );
@PUT("anime/{id}") @PUT("anime/{id}")
Call<String> updateAnime(@Path("id") int animeId, @Body AnimeEntity anime); Call<ApiResponse> updateAnime(@Path("id") int animeId, @Body AnimeEntity anime);
@DELETE("anime/delete/{id}") @DELETE("anime/delete/{id}")
Call<String> deleteAnime(@Path("id") int id); Call<ApiResponse> deleteAnime(@Path("id") int id);
// ---------------- Manga ---------------- // ---------------- Manga ----------------
@POST("manga/add") @POST("manga/add")
@ -69,15 +70,15 @@ public interface ApiService {
); );
@PUT("manga/{id}") @PUT("manga/{id}")
Call<String> updateManga(@Path("id") int mangaId, @Body MangaEntity manga); Call<ApiResponse> updateManga(@Path("id") int mangaId, @Body MangaEntity manga);
@DELETE("manga/delete/{id}") @DELETE("manga/delete/{id}")
Call<String> deleteManga(@Path("id") int id); Call<ApiResponse> deleteManga(@Path("id") int id);
// ---------------- Activity ------------------- // ---------------- Activity -------------------
@GET("user/{id}/stats") @GET("users/{id}/stats")
Call<Map<String, Map<String, Integer>>> getUserStats(@Path("id") int userId); Call<UserStatsResponse> getUserStats(@Path("id") int userId);
@GET("api/activity/list/{userId}") @GET("api/activity/list/{userId}")
Call<List<ActivityLog>> getActivityLog(@Path("userId") int userId); Call<List<ActivityLog>> getActivityLog(@Path("userId") int userId);

View File

@ -5,10 +5,10 @@ import java.util.Map;
public class UserStatsResponse { public class UserStatsResponse {
@SerializedName("anime") @SerializedName("animeStats")
private Map<String, Integer> animeStats; private Map<String, Integer> animeStats;
@SerializedName("manga") @SerializedName("mangaStats")
private Map<String, Integer> mangaStats; private Map<String, Integer> mangaStats;
public Map<String, Integer> getAnimeStats() { public Map<String, Integer> getAnimeStats() {

View File

@ -61,8 +61,8 @@ public class AddAnimeFragment extends Fragment {
searchResults.setLayoutManager(new LinearLayoutManager(getContext())); searchResults.setLayoutManager(new LinearLayoutManager(getContext()));
api = ApiClient.getClient().create(ApiService.class); api = ApiClient.getClient().create(ApiService.class);
SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE); SharedPreferences prefs = requireContext().getSharedPreferences("user_session", Context.MODE_PRIVATE);
userId = prefs.getInt("current_user_id", -1); userId = prefs.getInt("user_id", -1);
setupSpinners(); setupSpinners();
setupRecycler(); setupRecycler();
@ -125,7 +125,8 @@ public class AddAnimeFragment extends Fragment {
try { try {
score = Integer.parseInt(scoreEditText.getText().toString()); score = Integer.parseInt(scoreEditText.getText().toString());
progress = Integer.parseInt(progressEditText.getText().toString()); progress = Integer.parseInt(progressEditText.getText().toString());
} catch (NumberFormatException ignored) {} } catch (NumberFormatException ignored) {
}
AnimeEntity anime = new AnimeEntity(); AnimeEntity anime = new AnimeEntity();
anime.setUserId(userId); anime.setUserId(userId);
@ -163,9 +164,12 @@ public class AddAnimeFragment extends Fragment {
api.postActivity(actividad).enqueue(new Callback<>() { api.postActivity(actividad).enqueue(new Callback<>() {
@Override @Override
public void onResponse(Call call, Response response) {} public void onResponse(Call call, Response response) {
}
@Override @Override
public void onFailure(Call call, Throwable t) {} public void onFailure(Call call, Throwable t) {
}
}); });
} }
} }

View File

@ -59,8 +59,8 @@ public class AddMangaFragment extends Fragment {
searchResults.setLayoutManager(new LinearLayoutManager(getContext())); searchResults.setLayoutManager(new LinearLayoutManager(getContext()));
api = ApiClient.getClient().create(ApiService.class); api = ApiClient.getClient().create(ApiService.class);
SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE); SharedPreferences prefs = requireContext().getSharedPreferences("user_session", Context.MODE_PRIVATE);
userId = prefs.getInt("current_user_id", -1); userId = prefs.getInt("user_id", -1);
setupSpinners(); setupSpinners();
setupRecycler(); setupRecycler();
@ -123,7 +123,8 @@ public class AddMangaFragment extends Fragment {
try { try {
score = Integer.parseInt(scoreEditText.getText().toString()); score = Integer.parseInt(scoreEditText.getText().toString());
progress = Integer.parseInt(progressEditText.getText().toString()); progress = Integer.parseInt(progressEditText.getText().toString());
} catch (NumberFormatException ignored) {} } catch (NumberFormatException ignored) {
}
MangaEntity manga = new MangaEntity(); MangaEntity manga = new MangaEntity();
manga.setUserId(userId); manga.setUserId(userId);
@ -161,9 +162,12 @@ public class AddMangaFragment extends Fragment {
api.postActivity(actividad).enqueue(new Callback<>() { api.postActivity(actividad).enqueue(new Callback<>() {
@Override @Override
public void onResponse(Call call, Response response) {} public void onResponse(Call call, Response response) {
}
@Override @Override
public void onFailure(Call call, Throwable t) {} public void onFailure(Call call, Throwable t) {
}
}); });
} }
} }

View File

@ -5,6 +5,7 @@ import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -27,6 +28,7 @@ import com.santiparra.yomitrack.api.ApiClient;
import com.santiparra.yomitrack.api.ApiService; import com.santiparra.yomitrack.api.ApiService;
import com.santiparra.yomitrack.db.entities.AnimeEntity; import com.santiparra.yomitrack.db.entities.AnimeEntity;
import com.santiparra.yomitrack.model.AnimePageResponse; import com.santiparra.yomitrack.model.AnimePageResponse;
import com.santiparra.yomitrack.model.ApiResponse;
import com.santiparra.yomitrack.model.adapters.anime_adapter.AnimeAdapter; import com.santiparra.yomitrack.model.adapters.anime_adapter.AnimeAdapter;
import com.santiparra.yomitrack.ui.fragments.addanime.AddAnimeFragment; import com.santiparra.yomitrack.ui.fragments.addanime.AddAnimeFragment;
import com.santiparra.yomitrack.ui.fragments.editanime.EditAnimeFragment; import com.santiparra.yomitrack.ui.fragments.editanime.EditAnimeFragment;
@ -72,8 +74,8 @@ public class FragmentAnime extends Fragment {
btnViewNormal = view.findViewById(R.id.btnViewNormal); btnViewNormal = view.findViewById(R.id.btnViewNormal);
btnViewLarge = view.findViewById(R.id.btnViewLarge); btnViewLarge = view.findViewById(R.id.btnViewLarge);
FloatingActionButton fabAdd = view.findViewById(R.id.fabAddAnime); FloatingActionButton fabAdd = view.findViewById(R.id.fabAddAnime);
editSearch = view.findViewById(R.id.editSearch); editSearch = view.findViewById(R.id.editSearch);
editSearch.addTextChangedListener(new TextWatcher() { editSearch.addTextChangedListener(new TextWatcher() {
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { @Override public void onTextChanged(CharSequence s, int start, int before, int count) {
@ -155,9 +157,7 @@ public class FragmentAnime extends Fragment {
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
} }
adapter = new AnimeAdapter(animeList, viewType, adapter = new AnimeAdapter(animeList, viewType, this::showEditDialog, this::deleteAnime);
this::showEditDialog,
this::deleteAnime);
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
} }
@ -170,13 +170,14 @@ public class FragmentAnime extends Fragment {
} }
private void deleteAnime(AnimeEntity anime) { private void deleteAnime(AnimeEntity anime) {
api.deleteAnime(anime.getId()).enqueue(new Callback<String>() { api.deleteAnime(anime.getId()).enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(Call<String> call, Response<String> response) { public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
if (!isAdded()) return; if (!isAdded()) return;
if (response.isSuccessful()) { if (response.isSuccessful()) {
Toast.makeText(requireContext(), "Anime eliminado", Toast.LENGTH_SHORT).show(); String msg = response.body() != null ? response.body().getMessage() : "Anime eliminado";
Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show();
currentPage = 1; currentPage = 1;
animeList.clear(); animeList.clear();
loadMoreAnimes(currentPage); loadMoreAnimes(currentPage);
@ -186,7 +187,8 @@ public class FragmentAnime extends Fragment {
} }
@Override @Override
public void onFailure(Call<String> call, Throwable t) { public void onFailure(Call<ApiResponse> call, Throwable t) {
Log.e("API_RESPONSE", "Fallo al eliminar: " + t.getMessage(), t);
if (isAdded()) { if (isAdded()) {
Toast.makeText(requireContext(), "Fallo de conexión", Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), "Fallo de conexión", Toast.LENGTH_SHORT).show();
} }
@ -215,6 +217,7 @@ public class FragmentAnime extends Fragment {
@Override @Override
public void onFailure(Call<AnimePageResponse> call, Throwable t) { public void onFailure(Call<AnimePageResponse> call, Throwable t) {
Log.e("API_RESPONSE", "Error cargando más animes: " + t.getMessage(), t);
isLoading = false; isLoading = false;
if (isAdded()) { if (isAdded()) {
Toast.makeText(requireContext(), "Error al cargar más animes", Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), "Error al cargar más animes", Toast.LENGTH_SHORT).show();

View File

@ -3,6 +3,7 @@ package com.santiparra.yomitrack.ui.fragments.editanime;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -16,6 +17,7 @@ import com.santiparra.yomitrack.R;
import com.santiparra.yomitrack.api.ApiClient; import com.santiparra.yomitrack.api.ApiClient;
import com.santiparra.yomitrack.api.ApiService; import com.santiparra.yomitrack.api.ApiService;
import com.santiparra.yomitrack.db.entities.AnimeEntity; import com.santiparra.yomitrack.db.entities.AnimeEntity;
import com.santiparra.yomitrack.model.ApiResponse;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -54,10 +56,8 @@ public class EditAnimeFragment extends Fragment {
api = ApiClient.getClient().create(ApiService.class); api = ApiClient.getClient().create(ApiService.class);
// Llenar campos
fillFields(); fillFields();
// Spinner datos
String[] statusArray = getResources().getStringArray(R.array.anime_status_array); String[] statusArray = getResources().getStringArray(R.array.anime_status_array);
String[] typeArray = getResources().getStringArray(R.array.anime_type_array); String[] typeArray = getResources().getStringArray(R.array.anime_type_array);
@ -114,7 +114,7 @@ public class EditAnimeFragment extends Fragment {
return; return;
} }
int score = 0, progress = 0; int score, progress;
try { try {
score = Integer.parseInt(scoreStr); score = Integer.parseInt(scoreStr);
progress = Integer.parseInt(progressStr); progress = Integer.parseInt(progressStr);
@ -132,12 +132,17 @@ public class EditAnimeFragment extends Fragment {
anime.setStatus(status); anime.setStatus(status);
anime.setType(type); anime.setType(type);
api.updateAnime(anime.getId(), anime).enqueue(new Callback<String>() { api.updateAnime(anime.getId(), anime).enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(Call<String> call, Response<String> response) { public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
Log.d("API_RESPONSE", "onResponse ejecutado: " + response.body());
if (!isAdded()) return;
if (response.isSuccessful()) { if (response.isSuccessful()) {
Toast.makeText(requireContext(), "Anime actualizado", Toast.LENGTH_SHORT).show(); String message = response.body() != null ? response.body().getMessage() : "Anime actualizado";
requireContext().getSharedPreferences("user_profile", Context.MODE_PRIVATE) Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show();
requireContext().getSharedPreferences("user_session", Context.MODE_PRIVATE)
.edit().putBoolean("refresh_profile", true).apply(); .edit().putBoolean("refresh_profile", true).apply();
requireActivity().getSupportFragmentManager().popBackStack(); requireActivity().getSupportFragmentManager().popBackStack();
} else { } else {
@ -146,19 +151,24 @@ public class EditAnimeFragment extends Fragment {
} }
@Override @Override
public void onFailure(Call<String> call, Throwable t) { public void onFailure(Call<ApiResponse> call, Throwable t) {
Log.e("API_RESPONSE", "onFailure ejecutado: " + t.getMessage(), t);
if (!isAdded()) return;
Toast.makeText(requireContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show();
} }
}); });
} }
private void deleteAnime() { private void deleteAnime() {
api.deleteAnime(anime.getId()).enqueue(new Callback<String>() { api.deleteAnime(anime.getId()).enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(Call<String> call, Response<String> response) { public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
if (!isAdded()) return;
if (response.isSuccessful()) { if (response.isSuccessful()) {
Toast.makeText(requireContext(), "Anime eliminado", Toast.LENGTH_SHORT).show(); String message = response.body() != null ? response.body().getMessage() : "Anime eliminado";
requireContext().getSharedPreferences("user_profile", Context.MODE_PRIVATE) Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show();
requireContext().getSharedPreferences("user_session", Context.MODE_PRIVATE)
.edit().putBoolean("refresh_profile", true).apply(); .edit().putBoolean("refresh_profile", true).apply();
requireActivity().getSupportFragmentManager().popBackStack(); requireActivity().getSupportFragmentManager().popBackStack();
} else { } else {
@ -167,7 +177,9 @@ public class EditAnimeFragment extends Fragment {
} }
@Override @Override
public void onFailure(Call<String> call, Throwable t) { public void onFailure(Call<ApiResponse> call, Throwable t) {
Log.e("API_RESPONSE", "onFailure eliminar: " + t.getMessage(), t);
if (!isAdded()) return;
Toast.makeText(requireContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show();
} }
}); });

View File

@ -3,6 +3,7 @@ package com.santiparra.yomitrack.ui.fragments.editmanga;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -16,6 +17,7 @@ import com.santiparra.yomitrack.R;
import com.santiparra.yomitrack.api.ApiClient; import com.santiparra.yomitrack.api.ApiClient;
import com.santiparra.yomitrack.api.ApiService; import com.santiparra.yomitrack.api.ApiService;
import com.santiparra.yomitrack.db.entities.MangaEntity; import com.santiparra.yomitrack.db.entities.MangaEntity;
import com.santiparra.yomitrack.model.ApiResponse;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -40,8 +42,7 @@ public class EditMangaFragment extends Fragment {
} }
@Override @Override
public void onViewCreated(@NonNull View view, public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
@Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
editTextTitle = view.findViewById(R.id.editTextMangaTitle); editTextTitle = view.findViewById(R.id.editTextMangaTitle);
@ -112,7 +113,7 @@ public class EditMangaFragment extends Fragment {
return; return;
} }
int score = 0, progress = 0; int score, progress;
try { try {
score = Integer.parseInt(scoreStr); score = Integer.parseInt(scoreStr);
progress = Integer.parseInt(progressStr); progress = Integer.parseInt(progressStr);
@ -130,12 +131,17 @@ public class EditMangaFragment extends Fragment {
manga.setStatus(status); manga.setStatus(status);
manga.setType(type); manga.setType(type);
api.updateManga(manga.getId(), manga).enqueue(new Callback<String>() { api.updateManga(manga.getId(), manga).enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(Call<String> call, Response<String> response) { public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
Log.d("API_RESPONSE", "onResponse ejecutado: " + response.body());
if (!isAdded()) return;
if (response.isSuccessful()) { if (response.isSuccessful()) {
Toast.makeText(requireContext(), "Manga actualizado", Toast.LENGTH_SHORT).show(); String message = response.body() != null ? response.body().getMessage() : "Manga actualizado";
requireContext().getSharedPreferences("user_profile", Context.MODE_PRIVATE) Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show();
requireContext().getSharedPreferences("user_session", Context.MODE_PRIVATE)
.edit().putBoolean("refresh_profile", true).apply(); .edit().putBoolean("refresh_profile", true).apply();
requireActivity().getSupportFragmentManager().popBackStack(); requireActivity().getSupportFragmentManager().popBackStack();
} else { } else {
@ -144,19 +150,24 @@ public class EditMangaFragment extends Fragment {
} }
@Override @Override
public void onFailure(Call<String> call, Throwable t) { public void onFailure(Call<ApiResponse> call, Throwable t) {
Log.e("API_RESPONSE", "onFailure ejecutado: " + t.getMessage(), t);
if (!isAdded()) return;
Toast.makeText(requireContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show();
} }
}); });
} }
private void deleteManga() { private void deleteManga() {
api.deleteManga(manga.getId()).enqueue(new Callback<String>() { api.deleteManga(manga.getId()).enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(Call<String> call, Response<String> response) { public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
if (!isAdded()) return;
if (response.isSuccessful()) { if (response.isSuccessful()) {
Toast.makeText(requireContext(), "Manga eliminado", Toast.LENGTH_SHORT).show(); String message = response.body() != null ? response.body().getMessage() : "Manga eliminado";
requireContext().getSharedPreferences("user_profile", Context.MODE_PRIVATE) Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show();
requireContext().getSharedPreferences("user_session", Context.MODE_PRIVATE)
.edit().putBoolean("refresh_profile", true).apply(); .edit().putBoolean("refresh_profile", true).apply();
requireActivity().getSupportFragmentManager().popBackStack(); requireActivity().getSupportFragmentManager().popBackStack();
} else { } else {
@ -165,7 +176,9 @@ public class EditMangaFragment extends Fragment {
} }
@Override @Override
public void onFailure(Call<String> call, Throwable t) { public void onFailure(Call<ApiResponse> call, Throwable t) {
Log.e("API_RESPONSE", "onFailure eliminar: " + t.getMessage(), t);
if (!isAdded()) return;
Toast.makeText(requireContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show();
} }
}); });

View File

@ -5,6 +5,7 @@ import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -27,6 +28,7 @@ import com.santiparra.yomitrack.api.ApiClient;
import com.santiparra.yomitrack.api.ApiService; import com.santiparra.yomitrack.api.ApiService;
import com.santiparra.yomitrack.db.entities.MangaEntity; import com.santiparra.yomitrack.db.entities.MangaEntity;
import com.santiparra.yomitrack.model.MangaPageResponse; import com.santiparra.yomitrack.model.MangaPageResponse;
import com.santiparra.yomitrack.model.ApiResponse;
import com.santiparra.yomitrack.model.adapters.manga_adapter.MangaAdapter; import com.santiparra.yomitrack.model.adapters.manga_adapter.MangaAdapter;
import com.santiparra.yomitrack.ui.fragments.addmanga.AddMangaFragment; import com.santiparra.yomitrack.ui.fragments.addmanga.AddMangaFragment;
import com.santiparra.yomitrack.ui.fragments.editmanga.EditMangaFragment; import com.santiparra.yomitrack.ui.fragments.editmanga.EditMangaFragment;
@ -48,7 +50,7 @@ public class FragmentManga extends Fragment {
private ImageButton btnViewCompact, btnViewNormal, btnViewLarge; private ImageButton btnViewCompact, btnViewNormal, btnViewLarge;
private int currentViewType = MangaAdapter.VIEW_NORMAL; private int currentViewType = MangaAdapter.VIEW_NORMAL;
private List<MangaEntity> mangaList = new ArrayList<>(); private final List<MangaEntity> mangaList = new ArrayList<>();
private boolean isLoading = false; private boolean isLoading = false;
private int currentPage = 1; private int currentPage = 1;
@ -91,7 +93,6 @@ public class FragmentManga extends Fragment {
return; return;
} }
fabAdd.setOnClickListener(v -> requireActivity().getSupportFragmentManager() fabAdd.setOnClickListener(v -> requireActivity().getSupportFragmentManager()
.beginTransaction() .beginTransaction()
.replace(R.id.frame_layout, new AddMangaFragment()) .replace(R.id.frame_layout, new AddMangaFragment())
@ -168,12 +169,14 @@ public class FragmentManga extends Fragment {
} }
private void deleteManga(MangaEntity manga) { private void deleteManga(MangaEntity manga) {
api.deleteManga(manga.getId()).enqueue(new Callback<String>() { api.deleteManga(manga.getId()).enqueue(new Callback<ApiResponse>() {
@Override @Override
public void onResponse(Call<String> call, Response<String> response) { public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
if (!isAdded()) return; if (!isAdded()) return;
if (response.isSuccessful()) { if (response.isSuccessful()) {
Toast.makeText(requireContext(), "Manga eliminado", Toast.LENGTH_SHORT).show(); String msg = response.body() != null ? response.body().getMessage() : "Manga eliminado";
Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show();
currentPage = 1; currentPage = 1;
mangaList.clear(); mangaList.clear();
loadMoreMangas(currentPage); loadMoreMangas(currentPage);
@ -183,7 +186,8 @@ public class FragmentManga extends Fragment {
} }
@Override @Override
public void onFailure(Call<String> call, Throwable t) { public void onFailure(Call<ApiResponse> call, Throwable t) {
Log.e("API_RESPONSE", "Fallo al eliminar manga: " + t.getMessage(), t);
if (isAdded()) { if (isAdded()) {
Toast.makeText(requireContext(), "Fallo de conexión", Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), "Fallo de conexión", Toast.LENGTH_SHORT).show();
} }
@ -197,6 +201,7 @@ public class FragmentManga extends Fragment {
@Override @Override
public void onResponse(Call<MangaPageResponse> call, Response<MangaPageResponse> response) { public void onResponse(Call<MangaPageResponse> call, Response<MangaPageResponse> response) {
if (!isAdded()) return; if (!isAdded()) return;
if (response.isSuccessful() && response.body() != null) { if (response.isSuccessful() && response.body() != null) {
List<MangaEntity> nuevos = response.body().getData(); List<MangaEntity> nuevos = response.body().getData();
mangaList.addAll(nuevos); mangaList.addAll(nuevos);
@ -209,6 +214,7 @@ public class FragmentManga extends Fragment {
@Override @Override
public void onFailure(Call<MangaPageResponse> call, Throwable t) { public void onFailure(Call<MangaPageResponse> call, Throwable t) {
Log.e("API_RESPONSE", "Error al cargar mangas: " + t.getMessage(), t);
isLoading = false; isLoading = false;
if (isAdded()) { if (isAdded()) {
Toast.makeText(requireContext(), "Error al cargar más mangas", Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), "Error al cargar más mangas", Toast.LENGTH_SHORT).show();

View File

@ -2,24 +2,22 @@ package com.santiparra.yomitrack.ui.fragments.profile;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.*;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.santiparra.yomitrack.R; import com.santiparra.yomitrack.R;
import com.santiparra.yomitrack.api.ApiClient; import com.santiparra.yomitrack.api.ApiClient;
import com.santiparra.yomitrack.api.ApiService; import com.santiparra.yomitrack.api.ApiService;
import com.santiparra.yomitrack.model.UserStatsResponse;
import com.santiparra.yomitrack.utils.ActivityLog; import com.santiparra.yomitrack.utils.ActivityLog;
import org.json.JSONObject; import org.json.JSONObject;
@ -42,11 +40,12 @@ public class FragmentProfile extends Fragment {
private ApiService api; private ApiService api;
private int userId; private int userId;
private String username; private String username;
private View view;
@Nullable @Nullable
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_profile, container, false); view = inflater.inflate(R.layout.fragment_profile, container, false);
avatarImage = view.findViewById(R.id.avatarImage); avatarImage = view.findViewById(R.id.avatarImage);
coverImage = view.findViewById(R.id.coverImage); coverImage = view.findViewById(R.id.coverImage);
@ -59,12 +58,11 @@ public class FragmentProfile extends Fragment {
mangaStatsContainer = view.findViewById(R.id.mangaStatsContainer); mangaStatsContainer = view.findViewById(R.id.mangaStatsContainer);
activityContainer = view.findViewById(R.id.activityContainer); activityContainer = view.findViewById(R.id.activityContainer);
SharedPreferences prefs = requireContext().getSharedPreferences("user_prefs", Context.MODE_PRIVATE); SharedPreferences prefs = requireContext().getSharedPreferences("user_session", Context.MODE_PRIVATE);
userId = prefs.getInt("userId", -1); userId = prefs.getInt("user_id", -1);
username = prefs.getString("username", "Usuario"); username = prefs.getString("username", "Usuario");
api = ApiClient.getClient().create(ApiService.class); api = ApiClient.getClient().create(ApiService.class);
usernameText.setText(username); usernameText.setText(username);
loadStats(); loadStats();
@ -76,26 +74,43 @@ public class FragmentProfile extends Fragment {
return view; return view;
} }
private void loadStats() { @Override
api.getUserStats(userId).enqueue(new Callback<Map<String, Map<String, Integer>>>() { public void onResume() {
@Override super.onResume();
public void onResponse(Call<Map<String, Map<String, Integer>>> call, Response<Map<String, Map<String, Integer>>> response) { loadStats();
if (response.isSuccessful() && response.body() != null) { loadActivity();
Map<String, Integer> animeStats = response.body().get("animeStats"); }
Map<String, Integer> mangaStats = response.body().get("mangaStats");
populateStats(animeStatsContainer, animeStats); private void loadStats() {
populateStats(mangaStatsContainer, mangaStats); api.getUserStats(userId).enqueue(new Callback<UserStatsResponse>() {
@Override
public void onResponse(Call<UserStatsResponse> call, Response<UserStatsResponse> response) {
if (response.isSuccessful() && response.body() != null) {
populateStats(animeStatsContainer, response.body().getAnimeStats());
populateStats(mangaStatsContainer, response.body().getMangaStats());
} else {
Toast.makeText(getContext(), "Error al obtener estadísticas", Toast.LENGTH_SHORT).show();
} }
} }
@Override @Override
public void onFailure(Call<Map<String, Map<String, Integer>>> call, Throwable t) {} public void onFailure(Call<UserStatsResponse> call, Throwable t) {
Toast.makeText(getContext(), "Error de conexión al cargar stats", Toast.LENGTH_SHORT).show();
}
}); });
} }
private void populateStats(LinearLayout container, Map<String, Integer> stats) { private void populateStats(LinearLayout container, Map<String, Integer> stats) {
container.removeAllViews(); container.removeAllViews();
if (stats == null || stats.isEmpty()) {
TextView noData = new TextView(getContext());
noData.setText("No hay estadísticas disponibles");
noData.setPadding(16, 8, 16, 8);
container.addView(noData);
return;
}
int total = 0; int total = 0;
for (int count : stats.values()) total += count; for (int count : stats.values()) total += count;
@ -108,10 +123,32 @@ public class FragmentProfile extends Fragment {
label.setText(String.format(Locale.getDefault(), "%s • %d", entry.getKey(), entry.getValue())); label.setText(String.format(Locale.getDefault(), "%s • %d", entry.getKey(), entry.getValue()));
int progress = total > 0 ? (entry.getValue() * 100 / total) : 0; int progress = total > 0 ? (entry.getValue() * 100 / total) : 0;
bar.setProgress(progress); bar.setProgress(progress);
// Usar método compatible para aplicar color de estado
int color = getColorForStatus(entry.getKey());
bar.setProgressTintList(ColorStateList.valueOf(color));
container.addView(statView); container.addView(statView);
} }
} }
private int getColorForStatus(String status) {
switch (status.toLowerCase(Locale.ROOT)) {
case "watching":
return requireContext().getColor(R.color.status_watching);
case "completed":
return requireContext().getColor(R.color.status_completed);
case "paused":
return requireContext().getColor(R.color.status_paused);
case "dropped":
return requireContext().getColor(R.color.status_dropped);
case "planning":
return requireContext().getColor(R.color.status_planning);
default:
return requireContext().getColor(R.color.gray);
}
}
private void loadActivity() { private void loadActivity() {
api.getActivityLog(userId).enqueue(new Callback<List<ActivityLog>>() { api.getActivityLog(userId).enqueue(new Callback<List<ActivityLog>>() {
@Override @Override
@ -132,7 +169,9 @@ public class FragmentProfile extends Fragment {
} }
@Override @Override
public void onFailure(Call<List<ActivityLog>> call, Throwable t) {} public void onFailure(Call<List<ActivityLog>> call, Throwable t) {
Toast.makeText(getContext(), "Error al cargar actividad", Toast.LENGTH_SHORT).show();
}
}); });
} }
@ -167,7 +206,6 @@ public class FragmentProfile extends Fragment {
private void saveBiography() { private void saveBiography() {
String bio = editBiography.getText().toString().trim(); String bio = editBiography.getText().toString().trim();
// Aquí podrías guardar biografía en base de datos si se desea.
Toast.makeText(getContext(), "Biografía guardada", Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), "Biografía guardada", Toast.LENGTH_SHORT).show();
} }
} }

Binary file not shown.

View File

@ -1,20 +1,18 @@
<!-- progress_bar.xml -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Fondo gris -->
<!-- Fondo gris oscuro de la barra -->
<item android:id="@android:id/background"> <item android:id="@android:id/background">
<shape android:shape="rectangle"> <shape android:shape="rectangle">
<solid android:color="#E0E0E0" />
<corners android:radius="50dp" /> <corners android:radius="50dp" />
<solid android:color="@color/gray" />
</shape> </shape>
</item> </item>
<!-- Progreso de la barra --> <!-- Progreso (color por defecto, se sobrescribe desde Java) -->
<item android:id="@android:id/progress"> <item android:id="@android:id/progress">
<clip> <clip>
<shape android:shape="rectangle"> <shape android:shape="rectangle">
<solid android:color="#FFFFFF" /> <!-- No uses referencia aquí -->
<corners android:radius="50dp" /> <corners android:radius="50dp" />
<solid android:color="@color/primary" />
</shape> </shape>
</clip> </clip>
</item> </item>

View File

@ -20,8 +20,10 @@
android:id="@+id/statProgressBar" android:id="@+id/statProgressBar"
style="?android:attr/progressBarStyleHorizontal" style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="10dp" android:layout_height="16dp"
android:max="100" android:max="100"
android:progress="0" android:progress="0"
android:progressDrawable="@drawable/progress_bar" /> android:progressDrawable="@drawable/progress_bar"
android:layout_marginTop="4dp"
android:layout_marginBottom="8dp"/>
</LinearLayout> </LinearLayout>