diff --git a/AppTrabajadores/app/src/main/AndroidManifest.xml b/AppTrabajadores/app/src/main/AndroidManifest.xml index 939fbc2..d9cf50f 100644 --- a/AppTrabajadores/app/src/main/AndroidManifest.xml +++ b/AppTrabajadores/app/src/main/AndroidManifest.xml @@ -9,9 +9,9 @@ android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" - android:icon="@mipmap/ic_launcher" + android:icon="@mipmap/icon" android:label="@string/app_name" - android:roundIcon="@mipmap/ic_launcher_round" + android:roundIcon="@mipmap/icon_round" android:supportsRtl="true" android:theme="@style/Theme.AppTrabajadores" tools:targetApi="31"> diff --git a/AppTrabajadores/app/src/main/icon-playstore.png b/AppTrabajadores/app/src/main/icon-playstore.png new file mode 100644 index 0000000..80822e5 Binary files /dev/null and b/AppTrabajadores/app/src/main/icon-playstore.png differ diff --git a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/interfaces/IOnClickOnBackButtonListener.java b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/interfaces/IOnClickOnBackButtonListener.java new file mode 100644 index 0000000..51e6e7a --- /dev/null +++ b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/interfaces/IOnClickOnBackButtonListener.java @@ -0,0 +1,7 @@ +package com.andresgmoran.apptrabajadores.interfaces; + +import androidx.fragment.app.Fragment; + +public interface IOnClickOnBackButtonListener { + void onClickOnBackButton(); +} diff --git a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/network/ApiClient.java b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/network/ApiClient.java index e51bcf9..8e3d6d0 100644 --- a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/network/ApiClient.java +++ b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/network/ApiClient.java @@ -6,13 +6,11 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Handler; import android.os.Looper; -import android.util.Log; import androidx.security.crypto.EncryptedSharedPreferences; import androidx.security.crypto.MasterKey; import com.andresgmoran.apptrabajadores.models.ActivityState; -import com.andresgmoran.apptrabajadores.models.User; import com.andresgmoran.apptrabajadores.utils.SecurePreferencesUtil; import java.io.BufferedReader; @@ -20,13 +18,30 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; -import java.time.LocalDate; import java.time.LocalDateTime; public class ApiClient { private static final String BASE_URL = "http://10.0.2.2:8080"; + // Endpoints + private static final String ENDPOINT_GET_USERS = "/resi/user/getAll"; + private static final String ENDPOINT_GET_ME = "/resi/user/me"; + private static final String ENDPOINT_GET_RESIDENTS = "/resi/resident/getAll"; + private static final String ENDPOINT_GET_GAMES = "/resi/juego/getAll"; + private static final String ENDPOINT_GET_STATS = "/resi/registro/getAll"; + private static final String ENDPOINT_GET_ACTIVITIES = "/resi/evento/getAll"; + private static final String ENDPOINT_ADD_EVENT = "/resi/evento/add"; + private static final String ENDPOINT_LOGIN = "/auth/login"; + private static final String ENDPOINT_COMMENT_GAMESTAT = "/resi/registro/%d/addComment"; + private static final String ENDPOINT_UPDATE_ACTIVITY_STATE = "/resi/evento/%d/update"; + private static final String ENDPOINT_DELETE_GAMESTAT = "/resi/registro/%d/delete"; + private static final String ENDPOINT_DELETE_ACTIVITY = "/resi/evento/%d/delete"; + private static final String ENDPOINT_ACTIVITY_PARTICIPANTS = "/resi/evento/%d/participante/getAll"; + private static final String ENDPOINT_ADD_PARTICIPANT = "/resi/evento/%d/participante/add"; + private static final String ENDPOINT_UPDATE_PARTICIPANT = "/resi/evento/%d/participante/%d/update"; + private static final String ENDPOINT_TAKE_OUT_RESIDENT = "/resi/resident/%d/baja"; + public interface RawCallback { void onSuccess(String jsonText); void onError(String error); @@ -37,73 +52,81 @@ public class ApiClient { void onError(String error); } - - /** - * - * @param context - * @param callback - */ public static void getUsers(Context context, RawCallback callback) { - long idResidence = SecurePreferencesUtil.getLong(context, "idResidence", -1); - makeGetRequest(context, "/resi/user/getAll", callback); + makeGetRequest(context, ENDPOINT_GET_USERS, callback); } public static void getActualUser(Context context, RawCallback callback) { - makeGetRequest(context, "/resi/user/me", callback); + makeGetRequest(context, ENDPOINT_GET_ME, callback); } - /** - * - * @param context - * @param callback - */ public static void getResidents(Context context, RawCallback callback) { - long idResidence = SecurePreferencesUtil.getLong(context, "idResidence", -1); - makeGetRequest(context, "/resi/resident/getAll", callback); + makeGetRequest(context, ENDPOINT_GET_RESIDENTS, callback); } - /** - * - * @param context - * @param callback - */ public static void getGames(Context context, RawCallback callback) { - long idResidence = SecurePreferencesUtil.getLong(context, "idResidence", -1); - makeGetRequest(context, "/resi/juego/getAll", callback); + makeGetRequest(context, ENDPOINT_GET_GAMES, callback); } - /** - * - * @param context - * @param callback - */ public static void getGamesStats(Context context, RawCallback callback) { - long idResidence = SecurePreferencesUtil.getLong(context, "idResidence", -1); - makeGetRequest(context, "/resi/registro/getAll", callback); + makeGetRequest(context, ENDPOINT_GET_STATS, callback); } - /** - * - * @param context - * @param callback - */ public static void getAllActivities(Context context, RawCallback callback) { - long idResidence = SecurePreferencesUtil.getLong(context, "idResidence", -1); - makeGetRequest(context, "/resi/evento/getAll", callback); + makeGetRequest(context, ENDPOINT_GET_ACTIVITIES, callback); } public static void getAllParticipants(Context context, Long idActivity, RawCallback callback) { - long idResidence = SecurePreferencesUtil.getLong(context, "idResidence", -1); - makeGetRequest(context, "/resi/evento/" + idActivity + "/participante/getAll", callback); + makeGetRequest(context, String.format(ENDPOINT_ACTIVITY_PARTICIPANTS, idActivity), callback); } - /** - * - * @param context - * @param endpoint - * @param callback - */ - private static void makeGetRequest(Context context, String endpoint, RawCallback callback) { + public static void postLogin(String email, String password, RawCallback callback) { + String jsonBody = String.format("{\"email\":\"%s\", \"password\":\"%s\"}", email, password); + makePostRequest(null, ENDPOINT_LOGIN, jsonBody, callback); + } + + public static void postEvento(Context context, String nombre, String descripcion, LocalDateTime fecha, RawCallback callback) { + String jsonBody = String.format("{\"nombre\":\"%s\", \"descripcion\":\"%s\", \"fecha\":\"%s\", \"estado\":\"%s\"}", + nombre, descripcion, fecha.toString(), ActivityState.ABIERTO); + makePostRequest(context, ENDPOINT_ADD_EVENT, jsonBody, callback); + } + + public static void postParticipant(Context context, Long residentId, boolean humanHelp, boolean materialHelp, + String opinionPre, String opinionPost, Long idActivity, RawCallback callback) { + String jsonBody = String.format( + "{\"idResidente\":%d, \"recursosHumanos\":%b, \"recursosMateriales\":%b, \"preOpinion\":\"%s\", \"postOpinion\":\"%s\"}", + residentId, humanHelp, materialHelp, opinionPre, opinionPost); + makePostRequest(context, String.format(ENDPOINT_ADD_PARTICIPANT, idActivity), jsonBody, callback); + } + + public static void patchObservation(Context context, String observation, long idGameStat, RawCallback callback) { + String jsonBody = String.format("{\"observacion\":\"%s\"}", observation); + makePatchRequest(context, String.format(ENDPOINT_COMMENT_GAMESTAT, idGameStat), jsonBody, callback); + } + + public static void patchActivityState(Context context, long idActivity, ActivityState state, RawCallback callback) { + String jsonBody = String.format("{\"estado\":\"%s\"}", state); + makePatchRequest(context, String.format(ENDPOINT_UPDATE_ACTIVITY_STATE, idActivity), jsonBody, callback); + } + + public static void patchParticipant(Context context, long idActivity, long idParticipant, + String jsonBody, RawCallback callback) { + makePatchRequest(context, String.format(ENDPOINT_UPDATE_PARTICIPANT, idActivity, idParticipant), jsonBody, callback); + } + + public static void patchTakeOutResident(Context context, long idResident, RawCallback callback) { + makePatchRequest(context, String.format(ENDPOINT_TAKE_OUT_RESIDENT, idResident), "", callback); + } + + public static void deleteGameStat(Context context, long idGameStat, RawCallback callback) { + makeDeleteRequest(context, String.format(ENDPOINT_DELETE_GAMESTAT, idGameStat), callback); + } + + public static void deleteActivity(Context context, long idActivity, RawCallback callback) { + makeDeleteRequest(context, String.format(ENDPOINT_DELETE_ACTIVITY, idActivity), callback); + } + + public static void makeGetRequest(Context context, String endpoint, RawCallback callback) { new Thread(() -> { HttpURLConnection connection = null; BufferedReader reader = null; @@ -114,20 +137,7 @@ public class ApiClient { connection.setRequestMethod("GET"); connection.setRequestProperty("User-Agent", "Android"); - // Obtener el token desde EncryptedSharedPreferences - MasterKey masterKey = new MasterKey.Builder(context) - .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) - .build(); - - SharedPreferences encryptedPrefs = EncryptedSharedPreferences.create( - context, - "secure_auth", - masterKey, - EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, - EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM - ); - - String token = encryptedPrefs.getString("token", null); + String token = SecurePreferencesUtil.getString(context, "token", null); if (token != null) { connection.setRequestProperty("Authorization", "Bearer " + token); } @@ -136,109 +146,13 @@ public class ApiClient { connection.setReadTimeout(5000); int responseCode = connection.getResponseCode(); - if (responseCode == HttpURLConnection.HTTP_OK) { - reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); - StringBuilder json = new StringBuilder(); - String line; - - while ((line = reader.readLine()) != null) { - json.append(line); - } - - new Handler(Looper.getMainLooper()).post(() -> - callback.onSuccess(json.toString())); - } else { - new Handler(Looper.getMainLooper()).post(() -> - callback.onError("Código de error: " + responseCode)); - } - - } catch (Exception e) { - Log.e("API", "Error: " + e.getMessage(), e); - new Handler(Looper.getMainLooper()).post(() -> - callback.onError("Excepción: " + e.getMessage())); - } finally { - try { - if (reader != null) reader.close(); - if (connection != null) connection.disconnect(); - } catch (Exception ignored) {} - } - }).start(); - } - - /** - * - * @param email - * @param password - * @param callback - */ - public static void postLogin(String email, String password, RawCallback callback) { - String jsonBody = String.format("{\"email\":\"%s\", \"password\":\"%s\"}", email, password); - makePostRequest("/auth/login", jsonBody, callback); - } - - /** - * - * @param context - * @param nombre - * @param descripcion - * @param fecha - * @param callback - */ - public static void postEvento(Context context, String nombre, String descripcion, LocalDateTime fecha, RawCallback callback) { - String jsonBody = String.format("{\"nombre\":\"%s\", \"descripcion\":\"%s\", \"fecha\":\"%s\", \"estado\":\"%s\"}", nombre, descripcion, fecha.toString(), ActivityState.ABIERTO); - makePostRequest(context,"/resi/evento/add", jsonBody, callback); - } - - /** - * - * @param context - * @param residentId - * @param asistencia - * @param opinionPre - * @param opinionPost - * @param idActivity - * @param callback - */ - public static void postParticipant( Context context, Long residentId, boolean humanHelp, boolean materialHelp, String opinionPre, String opinionPost, Long idActivity, RawCallback callback) { - String jsonBody = String.format("{\"idResidente\":%d, \"recursosHumanos\":%b, \"recursosMateriales\":%b, \"preOpinion\":\"%s\", \"postOpinion\":\"%s\"}", residentId, humanHelp, materialHelp, opinionPre, opinionPost); long idResidence = SecurePreferencesUtil.getLong(context, "idResidence", -1); - makePostRequest(context,"/resi/evento/" + idActivity + "/participante/add", jsonBody, callback); - } - - /** - * - * @param endpoint - * @param jsonBody - * @param callback - */ - public static void makePostRequest(String endpoint, String jsonBody, RawCallback callback) { - new Thread(() -> { - HttpURLConnection connection = null; - - try { - URL url = new URL(BASE_URL + endpoint); - connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/json; utf-8"); - connection.setRequestProperty("Accept", "application/json"); - connection.setRequestProperty("User-Agent", "Android"); - connection.setDoOutput(true); - connection.setConnectTimeout(5000); - connection.setReadTimeout(5000); - - try (java.io.OutputStream os = connection.getOutputStream()) { - byte[] input = jsonBody.getBytes("utf-8"); - os.write(input, 0, input.length); - } - - int responseCode = connection.getResponseCode(); - java.io.InputStream inputStream = (responseCode >= 200 && responseCode < 300) + InputStream inputStream = (responseCode >= 200 && responseCode < 300) ? connection.getInputStream() : connection.getErrorStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "utf-8")); + reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder response = new StringBuilder(); String line; - while ((line = reader.readLine()) != null) { response.append(line.trim()); } @@ -256,18 +170,14 @@ public class ApiClient { new Handler(Looper.getMainLooper()).post(() -> callback.onError("Excepción: " + e.getMessage())); } finally { - if (connection != null) connection.disconnect(); + try { + if (reader != null) reader.close(); + if (connection != null) connection.disconnect(); + } catch (Exception ignored) {} } }).start(); } - /** - * - * @param context - * @param endpoint - * @param jsonBody - * @param callback - */ public static void makePostRequest(Context context, String endpoint, String jsonBody, RawCallback callback) { new Thread(() -> { HttpURLConnection connection = null; @@ -283,9 +193,11 @@ public class ApiClient { connection.setConnectTimeout(5000); connection.setReadTimeout(5000); - String token = SecurePreferencesUtil.getString(context, "token", null); - if (token != null) { - connection.setRequestProperty("Authorization", "Bearer " + token); + if (context != null) { + String token = SecurePreferencesUtil.getString(context, "token", null); + if (token != null) { + connection.setRequestProperty("Authorization", "Bearer " + token); + } } try (java.io.OutputStream os = connection.getOutputStream()) { @@ -294,7 +206,7 @@ public class ApiClient { } int responseCode = connection.getResponseCode(); - java.io.InputStream inputStream = (responseCode >= 200 && responseCode < 300) + InputStream inputStream = (responseCode >= 200 && responseCode < 300) ? connection.getInputStream() : connection.getErrorStream(); @@ -324,29 +236,11 @@ public class ApiClient { }).start(); } - public static void patchObservation(Context context, String observation, long idGameStat, RawCallback callback) { - String jsonBody = String.format("{\"observacion\":\"%s\"}", observation); - long idResidence = SecurePreferencesUtil.getLong(context, "idResidence", -1); - makePatchRequest(context,"/resi/registro/" + idGameStat + "/addComment", jsonBody, callback); - } - - public static void patchActivityState(Context context, long idActivity, ActivityState state, RawCallback callback) { - String jsonBody = String.format("{\"estado\":\"%s\"}", state); - makePatchRequest(context,"/resi/evento/" + idActivity + "/update", jsonBody, callback); - } - - public static void patchParticipant( Context context, long idActivity, long idParticipant, String jsonBody, RawCallback callback) { - makePatchRequest(context,"/resi/evento/" + idActivity + "/participante/" + idParticipant + "/update", jsonBody, callback); - } - - public static void patchTakeOutResident(Context context,long idResident, RawCallback callback) { - makePatchRequest(context,"/resi/resident/" + idResident + "/baja", "", callback); - } - public static void makePatchRequest(Context context, String endpoint, String jsonBody, RawCallback callback) { + // Puedes usar makePostRequest cambiando el método a PATCH si lo prefieres + // Aquí dejamos separado por claridad new Thread(() -> { HttpURLConnection connection = null; - try { URL url = new URL(BASE_URL + endpoint); connection = (HttpURLConnection) url.openConnection(); @@ -369,7 +263,7 @@ public class ApiClient { } int responseCode = connection.getResponseCode(); - java.io.InputStream inputStream = (responseCode >= 200 && responseCode < 300) + InputStream inputStream = (responseCode >= 200 && responseCode < 300) ? connection.getInputStream() : connection.getErrorStream(); @@ -399,24 +293,9 @@ public class ApiClient { }).start(); } - public static void deleteGameStat(Context context, long idGameStat, RawCallback callback) { - makeDeleteRequest(context,"/resi/registro/" + idGameStat + "/delete", callback); - } - - public static void deleteActivity(Context context, long idActivity, RawCallback callback) { - makeDeleteRequest(context,"/resi/evento/" + idActivity + "/delete", callback); - } - - /** - * - * @param context - * @param endpoint - * @param callback - */ public static void makeDeleteRequest(Context context, String endpoint, RawCallback callback) { new Thread(() -> { HttpURLConnection connection = null; - try { URL url = new URL(BASE_URL + endpoint); connection = (HttpURLConnection) url.openConnection(); @@ -426,14 +305,13 @@ public class ApiClient { connection.setConnectTimeout(5000); connection.setReadTimeout(5000); - // Añadir el token si está disponible String token = SecurePreferencesUtil.getString(context, "token", null); if (token != null) { connection.setRequestProperty("Authorization", "Bearer " + token); } int responseCode = connection.getResponseCode(); - java.io.InputStream inputStream = (responseCode >= 200 && responseCode < 300) + InputStream inputStream = (responseCode >= 200 && responseCode < 300) ? connection.getInputStream() : connection.getErrorStream(); @@ -465,12 +343,13 @@ public class ApiClient { public static void downloadImage(Context context, String imageUrl, ImageCallback callback) { new Thread(() -> { + HttpURLConnection connection = null; try { URL url = new URL(BASE_URL + imageUrl); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); - // Headers + // Autorización MasterKey masterKey = new MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); @@ -494,14 +373,11 @@ public class ApiClient { new Handler(Looper.getMainLooper()).post(() -> callback.onSuccess(bitmap)); } catch (Exception e) { - new Handler(Looper.getMainLooper()).post(() -> callback.onError(e.getMessage())); + new Handler(Looper.getMainLooper()).post(() -> callback.onError("Error al descargar imagen: " + e.getMessage())); + } finally { + if (connection != null) connection.disconnect(); } }).start(); } - - - - } - diff --git a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/repository/AppDataRepository.java b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/repository/AppDataRepository.java new file mode 100644 index 0000000..f2e020d --- /dev/null +++ b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/repository/AppDataRepository.java @@ -0,0 +1,436 @@ +package com.andresgmoran.apptrabajadores.repository; + +import android.content.Context; +import android.graphics.Bitmap; +import android.util.Log; + +import com.andresgmoran.apptrabajadores.models.Activity; +import com.andresgmoran.apptrabajadores.models.ActivityResident; +import com.andresgmoran.apptrabajadores.models.ActivityState; +import com.andresgmoran.apptrabajadores.models.Game; +import com.andresgmoran.apptrabajadores.models.Resident; +import com.andresgmoran.apptrabajadores.models.User; +import com.andresgmoran.apptrabajadores.models.gameStats.GameStat; +import com.andresgmoran.apptrabajadores.models.parsers.ActivityParser; +import com.andresgmoran.apptrabajadores.models.parsers.ActivityResidentParser; +import com.andresgmoran.apptrabajadores.models.parsers.GameParser; +import com.andresgmoran.apptrabajadores.models.parsers.GameStatParser; +import com.andresgmoran.apptrabajadores.models.parsers.ResidentParser; +import com.andresgmoran.apptrabajadores.models.parsers.UserParser; +import com.andresgmoran.apptrabajadores.network.ApiClient; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +public class AppDataRepository { + + private static final AppDataRepository instance = new AppDataRepository(); + + private User actualUser; + private Bitmap actualUserImage; + private List users = new ArrayList<>(); + private List residents = new ArrayList<>(); + private List games = new ArrayList<>(); + private List gameStats = new ArrayList<>(); + private List activities = new ArrayList<>(); + private List activityResidents = new ArrayList<>(); + + private AppDataRepository() {} + + public static AppDataRepository getInstance() { + return instance; + } + + // -------------------- Getters/Setters Básicos -------------------- + public User getActualUser() { return actualUser; } + public void setActualUser(User user) { this.actualUser = user; } + + public Bitmap getActualUserImage() { return actualUserImage; } + public void setActualUserImage(Bitmap image) { this.actualUserImage = image; } + + public List getUsers() { return users; } + public void setUsers(List list) { this.users = new ArrayList<>(list); } + + public List getResidents() { return residents; } + public void setResidents(List list) { this.residents = new ArrayList<>(list); } + + public List getGames() { return games; } + public void setGames(List list) { this.games = new ArrayList<>(list); } + + public List getGameStats() { return gameStats; } + public void setGameStats(List list) { this.gameStats = new ArrayList<>(list); } + + public List getActivities() { return activities; } + public void setActivities(List list) { this.activities = new ArrayList<>(list); } + + public List getActivityResidents() { return activityResidents; } + public void setActivityResidents(List list) { this.activityResidents = new ArrayList<>(list); } + + // -------------------- API Calls -------------------- + + public void fetchActualUser(Context context, Runnable onFinish) { + ApiClient.getActualUser(context, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + actualUser = UserParser.parseUser(jsonText); + fetchUserImage(context, actualUser.getAccountImage(), onFinish); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener usuario: " + error); + onFinish.run(); + } + }); + } + + private void fetchUserImage(Context context, String imageUrl, Runnable onFinish) { + ApiClient.downloadImage(context, imageUrl, new ApiClient.ImageCallback() { + @Override + public void onSuccess(Bitmap bitmap) { + actualUserImage = bitmap; + fetchUsers(context, onFinish); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener imagen de usuario: " + error); + onFinish.run(); + } + }); + } + + public void fetchUsers(Context context, Runnable onFinish) { + ApiClient.getUsers(context, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + users = UserParser.parseUsers(jsonText); + fetchResidents(context, onFinish); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener usuarios: " + error); + onFinish.run(); + } + }); + } + + public void fetchResidents(Context context, Runnable onFinish) { + ApiClient.getResidents(context, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + residents = ResidentParser.parseResidents(jsonText); + fetchGames(context, onFinish); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener residentes: " + error); + onFinish.run(); + } + }); + } + + public void fetchGames(Context context, Runnable onFinish) { + ApiClient.getGames(context, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + games = GameParser.parseGames(jsonText); + fetchGameStats(context, onFinish); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener juegos: " + error); + onFinish.run(); + } + }); + } + + public void fetchGameStats(Context context, Runnable onFinish) { + ApiClient.getGamesStats(context, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + gameStats = GameStatParser.parseStats(jsonText); + fetchActivities(context, onFinish); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener partidas: " + error); + onFinish.run(); + } + }); + } + + public void fetchActivities(Context context, Runnable onFinish) { + ApiClient.getAllActivities(context, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + activities = ActivityParser.parseActivities(jsonText); + if (activities.isEmpty()) { + onFinish.run(); + } else { + fetchAllParticipants(context, onFinish); + } + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener actividades: " + error); + onFinish.run(); + } + }); + } + + public void fetchAllParticipants(Context context, Runnable onFinish) { + activityResidents.clear(); + final int total = activities.size(); + final int[] completed = {0}; + + for (Activity activity : activities) { + ApiClient.getAllParticipants(context, activity.getId(), new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + List parsed = ActivityResidentParser.parseActivityResidents(jsonText); + synchronized (activityResidents) { + activityResidents.addAll(parsed); + } + checkDone(); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener participantes: " + error); + checkDone(); + } + + private void checkDone() { + synchronized (completed) { + completed[0]++; + if (completed[0] == total) { + onFinish.run(); + } + } + } + }); + } + } + + public void fetchActualUserOnly(Context context, Runnable onFinish) { + ApiClient.getActualUser(context, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + actualUser = UserParser.parseUser(jsonText); + onFinish.run(); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener usuario: " + error); + onFinish.run(); + } + }); + } + + public void fetchUserImageOnly(Context context, String imageUrl, Runnable onFinish) { + ApiClient.downloadImage(context, imageUrl, new ApiClient.ImageCallback() { + @Override + public void onSuccess(Bitmap bitmap) { + actualUserImage = bitmap; + onFinish.run(); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener imagen de usuario: " + error); + onFinish.run(); + } + }); + } + + public void fetchUsersOnly(Context context, Runnable onFinish) { + ApiClient.getUsers(context, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + users = UserParser.parseUsers(jsonText); + onFinish.run(); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener usuarios: " + error); + onFinish.run(); + } + }); + } + + public void fetchResidentsOnly(Context context, Runnable onFinish) { + ApiClient.getResidents(context, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + residents = ResidentParser.parseResidents(jsonText); + onFinish.run(); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener residentes: " + error); + onFinish.run(); + } + }); + } + + public void fetchGamesOnly(Context context, Runnable onFinish) { + ApiClient.getGames(context, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + games = GameParser.parseGames(jsonText); + onFinish.run(); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener juegos: " + error); + onFinish.run(); + } + }); + } + + public void fetchGameStatsOnly(Context context, Runnable onFinish) { + ApiClient.getGamesStats(context, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + gameStats = GameStatParser.parseStats(jsonText); + onFinish.run(); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener partidas: " + error); + onFinish.run(); + } + }); + } + + public void fetchActivitiesOnly(Context context, Runnable onFinish) { + ApiClient.getAllActivities(context, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + activities = ActivityParser.parseActivities(jsonText); + onFinish.run(); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener actividades: " + error); + onFinish.run(); + } + }); + } + + public void fetchParticipantsOnly(Context context, List sourceActivities, Runnable onFinish) { + activityResidents.clear(); + final int total = sourceActivities.size(); + final int[] completed = {0}; + + if (total == 0) { + onFinish.run(); + return; + } + + for (Activity activity : sourceActivities) { + ApiClient.getAllParticipants(context, activity.getId(), new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + List parsed = ActivityResidentParser.parseActivityResidents(jsonText); + synchronized (activityResidents) { + activityResidents.addAll(parsed); + } + checkDone(); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al obtener participantes: " + error); + checkDone(); + } + + private void checkDone() { + synchronized (completed) { + completed[0]++; + if (completed[0] == total) { + onFinish.run(); + } + } + } + }); + } + } + + + // -------------------- Otras acciones API -------------------- + + public void addActivity(Context context, String nombre, String descripcion, LocalDateTime fecha, Runnable onSuccess, Runnable onError) { + ApiClient.postEvento(context, nombre, descripcion, fecha, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + fetchActivities(context, onSuccess); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al añadir actividad: " + error); + onError.run(); + } + }); + } + + public void deleteGameStat(Context context, long id, Runnable onSuccess) { + ApiClient.deleteGameStat(context, id, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + fetchGameStats(context, onSuccess); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al borrar partida: " + error); + onSuccess.run(); // puede seguir aunque falle + } + }); + } + + public void updateObservation(Context context, String comment, long id, Runnable onSuccess) { + ApiClient.patchObservation(context, comment, id, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + fetchGameStats(context, onSuccess); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al actualizar observación: " + error); + onSuccess.run(); + } + }); + } + + public void changeActivityState(Context context, long id, ActivityState state, Runnable onSuccess) { + ApiClient.patchActivityState(context, id, state, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + fetchActivities(context, onSuccess); + } + + @Override + public void onError(String error) { + Log.e("API", "Error al cambiar estado: " + error); + onSuccess.run(); + } + }); + } +} + diff --git a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/MainActivity.java b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/MainActivity.java index 006a60b..1d33d2c 100644 --- a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/MainActivity.java +++ b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/MainActivity.java @@ -1,7 +1,5 @@ package com.andresgmoran.apptrabajadores.ui; -import static java.lang.Thread.sleep; - import android.content.SharedPreferences; import android.graphics.Bitmap; import android.os.Bundle; @@ -10,7 +8,12 @@ import android.view.MenuItem; import android.view.View; import android.widget.ProgressBar; import android.widget.Toast; - +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.fragment.app.Fragment; import com.andresgmoran.apptrabajadores.R; import com.andresgmoran.apptrabajadores.exceptions.ParserException; import com.andresgmoran.apptrabajadores.interfaces.IOChangeFragmentListener; @@ -21,6 +24,7 @@ import com.andresgmoran.apptrabajadores.interfaces.IOClickOnGameStatsListener; import com.andresgmoran.apptrabajadores.interfaces.IOClickOnParticipantListener; import com.andresgmoran.apptrabajadores.interfaces.IOClickOnResidentListener; import com.andresgmoran.apptrabajadores.interfaces.IOnChageStateActivityListener; +import com.andresgmoran.apptrabajadores.interfaces.IOnClickOnBackButtonListener; import com.andresgmoran.apptrabajadores.models.Activity; import com.andresgmoran.apptrabajadores.models.ActivityResident; import com.andresgmoran.apptrabajadores.models.ActivityState; @@ -35,44 +39,38 @@ import com.andresgmoran.apptrabajadores.models.parsers.GameStatParser; import com.andresgmoran.apptrabajadores.models.parsers.ResidentParser; import com.andresgmoran.apptrabajadores.models.parsers.UserParser; import com.andresgmoran.apptrabajadores.network.ApiClient; +import com.andresgmoran.apptrabajadores.ui.fragments.account.AccountFragment; +import com.andresgmoran.apptrabajadores.ui.fragments.account.EditAccountFragment; +import com.andresgmoran.apptrabajadores.ui.fragments.activities.ActivitiesFragment; import com.andresgmoran.apptrabajadores.ui.fragments.activities.ActivityDetailFragment; import com.andresgmoran.apptrabajadores.ui.fragments.activities.AddActivityFragment; import com.andresgmoran.apptrabajadores.ui.fragments.activities.OpinionFragment; import com.andresgmoran.apptrabajadores.ui.fragments.activities.ParticipantSelectionDialogFragment; +import com.andresgmoran.apptrabajadores.ui.fragments.authentication.LoginFragment; import com.andresgmoran.apptrabajadores.ui.fragments.game.GameFragment; import com.andresgmoran.apptrabajadores.ui.fragments.gameDetail.GameDetailFragment; -import com.andresgmoran.apptrabajadores.ui.fragments.authentication.LoginFragment; -import com.andresgmoran.apptrabajadores.ui.fragments.account.AccountFragment; -import com.andresgmoran.apptrabajadores.ui.fragments.account.EditAccountFragment; -import com.andresgmoran.apptrabajadores.ui.fragments.activities.ActivitiesFragment; import com.andresgmoran.apptrabajadores.ui.fragments.home.HomeFragment; import com.andresgmoran.apptrabajadores.ui.fragments.resident.ResidentFragment; -import com.andresgmoran.apptrabajadores.ui.fragments.residentList.ResidentsListFragment; import com.andresgmoran.apptrabajadores.utils.SecurePreferencesUtil; import com.google.android.material.bottomnavigation.BottomNavigationView; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.graphics.Insets; -import androidx.core.view.ViewCompat; -import androidx.core.view.WindowInsetsCompat; -import androidx.fragment.app.Fragment; - import com.google.android.material.navigation.NavigationBarView; - -import org.json.JSONObject; - -import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import org.json.JSONObject; +public class MainActivity extends AppCompatActivity implements + NavigationBarView.OnItemSelectedListener, IOChangeFragmentListener, IOnClickOnBackButtonListener, + LoginFragment.OnLoginListener, + HomeFragment.IOnAttachListener, + IOClickOnResidentListener, + IOClickOnGameListener, IOClickOnGameStatsListener, GameDetailFragment.IOnAddObservationListener, + IOClickOnActivityListener, AddActivityFragment.IOnAddActivity, IOnChageStateActivityListener, ActivitiesFragment.IOOnAttachListener, ActivityDetailFragment.IOOnAttachListener, + IOClickOnParticipantListener, IOClickOnAddParticipantListener, ParticipantSelectionDialogFragment.OnParticipantSelectedListener, + OpinionFragment.OnAddOpinionListener, + AccountFragment.IOAccountFragmentListener { -public class MainActivity extends AppCompatActivity implements NavigationBarView.OnItemSelectedListener, LoginFragment.OnLoginListener, IOChangeFragmentListener, IOClickOnResidentListener, IOClickOnGameStatsListener, IOClickOnGameListener, IOClickOnActivityListener, - ResidentsListFragment.IOOnAttachListener, HomeFragment.IOOnAttachListenerUser , HomeFragment.IOOnAttachListenerResidents, HomeFragment.IOOnAttachListenerGameStats, HomeFragment.IOOnAttachListenerGames, GameDetailFragment.IOnAddObservationListener, - AddActivityFragment.IOnAddActivity, IOnChageStateActivityListener, ActivitiesFragment.IOOnAttachListener, ActivityDetailFragment.IOOnAttachListener, IOClickOnParticipantListener, ParticipantSelectionDialogFragment.OnParticipantSelectedListener, IOClickOnAddParticipantListener, - OpinionFragment.OnAddOpinionListener, AccountFragment.IOAccountFragmentListener { + private Fragment lastFragment = null; private User actualUser; private Bitmap actualUserImage; @@ -104,9 +102,9 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView if (rememberPassword) { if (token != null && System.currentTimeMillis() < expiration) { - // Token válido getActualUserFromAPI(); } else { + Log.i( "AUTH", "Token no válido o expirado, intentando login automático"); // Token expirado: intentar login automático String email = SecurePreferencesUtil.getString(this, "email", null); String password = SecurePreferencesUtil.getString(this, "password", null); @@ -131,13 +129,13 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView } @Override + +// --------------------------------------------------------------------- NAVIGATION --------------------------------------------------------------------- public boolean onNavigationItemSelected(@NonNull MenuItem item) { Fragment f = null; int id = item.getItemId(); if (id == R.id.navigation_home) f = createHomeFragment(); - else if (id == R.id.navigation_list) - f = new ResidentsListFragment(); else if (id == R.id.navigation_activities) f = new ActivitiesFragment(); else if (id == R.id.navigation_account) @@ -235,11 +233,16 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView * @return true si se ha cargado correctamente, false si no */ private boolean loadFragment(Fragment fragment) { + if (fragment != null) { + Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fcvMain); + if (currentFragment != null) { + lastFragment = currentFragment; // guarda el actual como "anterior" + } + } if (fragment != null) { getSupportFragmentManager() .beginTransaction() .replace(R.id.fcvMain, fragment) - .addToBackStack(null) .commit(); return true; } @@ -325,31 +328,27 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView /** * */ - private void reloadCurrentFragment() { - Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fcvMain); - if (currentFragment == null) return; + private void reloadFragment(Fragment fragment) { + if (fragment == null) return; - Bundle args = currentFragment.getArguments(); + Bundle args = fragment.getArguments(); - if (currentFragment instanceof HomeFragment) { + if (fragment instanceof HomeFragment) { loadFragment(createHomeFragment()); - } else if (currentFragment instanceof ResidentsListFragment) { - loadFragment(new ResidentsListFragment()); - - } else if (currentFragment instanceof ResidentFragment && args != null) { + } else if (fragment instanceof ResidentFragment && args != null) { Resident resident = (Resident) args.getSerializable("resident"); if (resident != null) { loadFragment(createResidentFragment(resident)); } - } else if (currentFragment instanceof GameFragment && args != null) { + } else if (fragment instanceof GameFragment && args != null) { Game game = (Game) args.getSerializable("game"); if (game != null) { loadFragment(createGameFragment(game)); } - } else if (currentFragment instanceof GameDetailFragment && args != null) { + } else if (fragment instanceof GameDetailFragment && args != null) { GameStat originalStat = (GameStat) args.getSerializable("gameStat"); Resident resident = (Resident) args.getSerializable("gameStatResident"); Game game = (Game) args.getSerializable("gameStatGame"); @@ -367,23 +366,34 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView } } - } else if (currentFragment instanceof ActivitiesFragment) { + } else if (fragment instanceof ActivitiesFragment) { loadFragment(new ActivitiesFragment()); - } else if (currentFragment instanceof ActivityDetailFragment && args != null) { - Activity activity = (Activity) args.getSerializable("activity"); - if (activity != null) { - List participants = new ArrayList<>(); - for (ActivityResident ar : activityResidents) { - if (ar.getActivityId() == activity.getId()) { - participants.add(ar); + } else if (fragment instanceof ActivityDetailFragment && args != null) { + Activity originalActivity = (Activity) args.getSerializable("activity"); + if (originalActivity != null) { + Activity updatedActivity = null; + for (Activity act : activities) { + if (act.getId() == originalActivity.getId()) { + updatedActivity = act; + break; } } - loadFragment(createActivityDetailFragment(activity, participants)); + + if (updatedActivity != null) { + List participants = new ArrayList<>(); + for (ActivityResident ar : activityResidents) { + if (ar.getActivityId() == updatedActivity.getId()) { + participants.add(ar); + } + } + loadFragment(createActivityDetailFragment(updatedActivity, participants)); + } } } } + // --------------------------------------------------------------------- GET DATOS FROM API --------------------------------------------------------------------- /** @@ -523,7 +533,8 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView Log.e("ResidentParser", e.getMessage()); } - reloadCurrentFragment(); + Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fcvMain); + reloadFragment(currentFragment); } @Override @@ -605,7 +616,8 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView Log.e("GameStatParser", e.getMessage()); } - reloadCurrentFragment(); + Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fcvMain); + reloadFragment(currentFragment); } @Override @@ -737,7 +749,8 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView final int[] completedRequests = {0}; if (totalActivities == 0) { - reloadCurrentFragment(); + Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fcvMain); + reloadFragment(currentFragment); return; } @@ -763,10 +776,12 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView } private void checkAndReload() { + Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fcvMain); synchronized (completedRequests) { completedRequests[0]++; if (completedRequests[0] == totalActivities) { - runOnUiThread(() -> reloadCurrentFragment()); + runOnUiThread(() -> + reloadFragment(currentFragment)); } } } @@ -777,6 +792,9 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView // --------------------------------------------------------------------- OnClickListeners --------------------------------------------------------------------- + + // --------------------------------------------------------------------- Resident listeners --------------------------------------------------------------------- + /** * Listener para el click en un residente * @param resident residente sobre el que se ha hecho click @@ -787,6 +805,42 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView loadFragment(f); } + /** + * + * @param resident + */ + @Override + public void onTakeOutResident(Resident resident) { + ApiClient.patchTakeOutResident( MainActivity.this, resident.getId(), new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + Toast.makeText(MainActivity.this, "Residente dado de baja correctamente", Toast.LENGTH_SHORT).show(); + refreshResidentsAndReload(); + refreshGameStatsAndReload(); + } + + @Override + public void onError(String error) { + Toast.makeText(MainActivity.this, "Error al dar de baja a residente", Toast.LENGTH_SHORT).show(); + Log.e("API", "Error al eliminar residente: " + error); + } + }); + } + + // --------------------------------------------------------------------- Game listeners --------------------------------------------------------------------- + + /** + * Listener para el click en un juego + * @param game juego sobre el que se ha hecho click + */ + @Override + public void onClickOnGame(Game game) { + Fragment f = createGameFragment(game); + loadFragment(f); + } + + // --------------------------------------------------------------------- GameStats Listeners --------------------------------------------------------------------- + /** * Listener para el click en una partida * @param gameStat partida sobre la que se ha hecho click @@ -799,138 +853,62 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView } /** - * Listener para el click en un juego - * @param game juego sobre el que se ha hecho click + * + * @param gameStat + * @param gamestatGame */ @Override - public void onClickOnGame(Game game) { - Fragment f = createGameFragment(game); - loadFragment(f); + public void onDeleteGameStat(GameStat gameStat, Game gamestatGame) { + ApiClient.deleteGameStat(MainActivity.this, gameStat.getId(), new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + Toast.makeText(MainActivity.this, "Partida eliminada correctamente", Toast.LENGTH_SHORT).show(); + refreshGameStatsAndReload(); + } + + @Override + public void onError(String error) { + Toast.makeText(MainActivity.this, "Error al eliminar partida", Toast.LENGTH_SHORT).show(); + Log.e("API", "Error al eliminar partida: " + error); + } + }); } + /** + * + * @param observation + * @param gameId + * @param gameStatId + */ + @Override + public void onAddObservation(String observation, long gameId, long gameStatId) { + ApiClient.patchObservation(MainActivity.this, observation, gameStatId, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + Toast.makeText(MainActivity.this, "Observación añadida correctamente", Toast.LENGTH_SHORT).show(); + refreshGameStatsAndReload(); + } + + @Override + public void onError(String error) { + Toast.makeText(MainActivity.this, "Error al añadir observación", Toast.LENGTH_SHORT).show(); + Log.e("API", "Error al añadir observación: " + error); + } + }); + } + + // --------------------------------------------------------------------- Activity Listeners --------------------------------------------------------------------- + + /** + * + * @param activity + * @param participants + */ @Override public void onClickOnActivity(Activity activity, List participants) { loadFragment(createActivityDetailFragment(activity, participants)); } - @Override - public void onChangeStateActivity(Activity activity, ActivityState state) { - ApiClient.patchActivityState(MainActivity.this, activity.getId(), state, new ApiClient.RawCallback() { - @Override - public void onSuccess(String jsonText) { - Toast.makeText(MainActivity.this, "Actividad cerrada correctamente", Toast.LENGTH_SHORT).show(); - refreshActivitiesAndReload(); - } - - @Override - public void onError(String error) { - Toast.makeText(MainActivity.this, "Error al cerrar actividad", Toast.LENGTH_SHORT).show(); - Log.e("API", "Error al cerrar actividad: " + error); - } - }); - } - - @Override - public void onClickOnAddParticipant(Activity activity, List participants ,List residents) { - ParticipantSelectionDialogFragment dialog = new ParticipantSelectionDialogFragment(activity, participants, residents); - dialog.show(getSupportFragmentManager(), "ParticipantDialog"); - } - - @Override - public void onClickOnParticipant(ActivityResident participant) { - Toast.makeText( this, "Clicked on participant: " + participant.getIdResident() , Toast.LENGTH_SHORT).show(); - } - - @Override - public void onClickOnAssistance(ActivityResident participant, boolean assistance ) { - String jsonBody = "{\"asistenciaPermitida\": " + assistance + "}"; - ApiClient.patchParticipant( MainActivity.this, participant.getActivityId(), participant.getId() , jsonBody, new ApiClient.RawCallback() { - @Override - public void onSuccess(String jsonText) { - Toast.makeText(MainActivity.this, "Asistencia actualizada correctamente", Toast.LENGTH_SHORT).show(); - refreshActivitiesAndReload(); - } - - @Override - public void onError(String error) { - Toast.makeText(MainActivity.this, "Error al actualizar asistencia", Toast.LENGTH_SHORT).show(); - Log.e("API", "Error al actualizar asistencia: " + error); - } - }); - } - - @Override - public void onClickOnOpinion(ActivityResident participant, boolean isPreOpinion) { - Fragment f = new OpinionFragment(); - Bundle bundle = new Bundle(); - bundle.putSerializable("participant", participant); - bundle.putBoolean("isPreOpinion", isPreOpinion); - f.setArguments(bundle); - loadFragment(f); - } - - @Override - public void onAddOpinion(ActivityResident participant ,boolean isPreOpinion, String opinion) { - String jsonBody = ""; - if (isPreOpinion) { - jsonBody = "{\"preOpinion\": \"" + opinion + "\"}"; - } else { - jsonBody = "{\"postOpinion\": \"" + opinion + "\"}"; - } - ApiClient.patchParticipant( MainActivity.this, participant.getActivityId(), participant.getId() , jsonBody, new ApiClient.RawCallback() {; - @Override - public void onSuccess(String jsonText) { - Toast.makeText(MainActivity.this, "Opinion actualizada correctamente", Toast.LENGTH_SHORT).show(); - refreshActivitiesAndReload(); - } - - @Override - public void onError(String error) { - Toast.makeText(MainActivity.this, "Error al actualizar opinion", Toast.LENGTH_SHORT).show(); - Log.e("API", "Error al actualizar opinion: " + error); - } - }); - } - - @Override - public void onClickOnMaterialHelp(ActivityResident participant, boolean materialHelp) { - String jsonBody = "{\"recursosMateriales\": " + materialHelp + "}"; - ApiClient.patchParticipant( MainActivity.this, participant.getActivityId(), participant.getId() , jsonBody, new ApiClient.RawCallback() {; - @Override - public void onSuccess(String jsonText) { - Toast.makeText(MainActivity.this, "Ayuda material actualizada correctamente", Toast.LENGTH_SHORT).show(); - refreshActivitiesAndReload(); - } - - @Override - public void onError(String error) { - Toast.makeText(MainActivity.this, "Error al actualizar ayuda material", Toast.LENGTH_SHORT).show(); - Log.e("API", "Error al actualizar ayuda material: " + error); - } - }); - } - - @Override - public void onClickOnHumanHelp(ActivityResident participant, boolean humanHelp) { - String jsonBody = "{\"recursosHumanos\": " + humanHelp + "}"; - ApiClient.patchParticipant( MainActivity.this, participant.getActivityId(), participant.getId() , jsonBody, new ApiClient.RawCallback() {; - @Override - public void onSuccess(String jsonText) { - Toast.makeText(MainActivity.this, "Ayuda humana actualizada correctamente", Toast.LENGTH_SHORT).show(); - refreshActivitiesAndReload(); - } - - @Override - public void onError(String error) { - Toast.makeText(MainActivity.this, "Error al actualizar ayuda humana", Toast.LENGTH_SHORT).show(); - Log.e("API", "Error al actualizar ayuda humana: " + error); - } - }); - } - - - // --------------------------------------------------------------------- OnAddListeners --------------------------------------------------------------------- - /** * * @param activityName @@ -958,23 +936,175 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView /** * - * @param observation - * @param gameId - * @param gameStatId + * @param activity */ @Override - public void onAddObservation(String observation, long gameId, long gameStatId) { - ApiClient.patchObservation(MainActivity.this, observation, gameStatId, new ApiClient.RawCallback() { + public void onDeleteActivitie(Activity activity) { + ApiClient.deleteActivity(MainActivity.this, activity.getId(), new ApiClient.RawCallback() { @Override public void onSuccess(String jsonText) { - Toast.makeText(MainActivity.this, "Observación añadida correctamente", Toast.LENGTH_SHORT).show(); - refreshGameStatsAndReload(); + Toast.makeText(MainActivity.this, "Actividad eliminada correctamente", Toast.LENGTH_SHORT).show(); + refreshActivitiesAndReload(); } @Override public void onError(String error) { - Toast.makeText(MainActivity.this, "Error al añadir observación", Toast.LENGTH_SHORT).show(); - Log.e("API", "Error al añadir observación: " + error); + Toast.makeText(MainActivity.this, "Error al eliminar actividad", Toast.LENGTH_SHORT).show(); + Log.e("API", "Error al eliminar actividad: " + error); + } + }); + } + + @Override + public void onChangeStateActivity(Activity activity, ActivityState state) { + ApiClient.patchActivityState(MainActivity.this, activity.getId(), state, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + Toast.makeText(MainActivity.this, "Actividad cerrada correctamente", Toast.LENGTH_SHORT).show(); + refreshActivitiesAndReload(); + } + + @Override + public void onError(String error) { + Toast.makeText(MainActivity.this, "Error al cerrar actividad", Toast.LENGTH_SHORT).show(); + Log.e("API", "Error al cerrar actividad: " + error); + } + }); + } + + // --------------------------------------------------------------------- Participant Listeners --------------------------------------------------------------------- + + + /** + * + * @param activity + * @param participants + * @param residents + */ + @Override + public void onClickOnAddParticipant(Activity activity, List participants ,List residents) { + ParticipantSelectionDialogFragment dialog = new ParticipantSelectionDialogFragment(activity, participants, residents); + dialog.show(getSupportFragmentManager(), "ParticipantDialog"); + } + + /** + * + * @param participant + */ + @Override + public void onClickOnParticipant(ActivityResident participant) { + Toast.makeText( this, "Clicked on participant: " + participant.getIdResident() , Toast.LENGTH_SHORT).show(); + } + + /** + * + * @param participant + * @param assistance + */ + @Override + public void onClickOnAssistance(ActivityResident participant, boolean assistance ) { + String jsonBody = "{\"asistenciaPermitida\": " + assistance + "}"; + ApiClient.patchParticipant( MainActivity.this, participant.getActivityId(), participant.getId() , jsonBody, new ApiClient.RawCallback() { + @Override + public void onSuccess(String jsonText) { + Toast.makeText(MainActivity.this, "Asistencia actualizada correctamente", Toast.LENGTH_SHORT).show(); + refreshActivitiesAndReload(); + } + + @Override + public void onError(String error) { + Toast.makeText(MainActivity.this, "Error al actualizar asistencia", Toast.LENGTH_SHORT).show(); + Log.e("API", "Error al actualizar asistencia: " + error); + } + }); + } + + /** + * + * @param participant + * @param isPreOpinion + */ + @Override + public void onClickOnOpinion(ActivityResident participant, boolean isPreOpinion) { + Fragment f = new OpinionFragment(); + Bundle bundle = new Bundle(); + bundle.putSerializable("participant", participant); + bundle.putBoolean("isPreOpinion", isPreOpinion); + f.setArguments(bundle); + loadFragment(f); + } + + /** + * + * @param participant + * @param isPreOpinion + * @param opinion + */ + @Override + public void onAddOpinion(ActivityResident participant ,boolean isPreOpinion, String opinion) { + String jsonBody = ""; + if (isPreOpinion) { + jsonBody = "{\"preOpinion\": \"" + opinion + "\"}"; + } else { + jsonBody = "{\"postOpinion\": \"" + opinion + "\"}"; + } + ApiClient.patchParticipant( MainActivity.this, participant.getActivityId(), participant.getId() , jsonBody, new ApiClient.RawCallback() {; + @Override + public void onSuccess(String jsonText) { + Toast.makeText(MainActivity.this, "Opinion actualizada correctamente", Toast.LENGTH_SHORT).show(); + refreshActivitiesAndReload(); + } + + @Override + public void onError(String error) { + Toast.makeText(MainActivity.this, "Error al actualizar opinion", Toast.LENGTH_SHORT).show(); + Log.e("API", "Error al actualizar opinion: " + error); + } + }); + } + + /** + * + * @param participant + * @param materialHelp + */ + @Override + public void onClickOnMaterialHelp(ActivityResident participant, boolean materialHelp) { + String jsonBody = "{\"recursosMateriales\": " + materialHelp + "}"; + ApiClient.patchParticipant( MainActivity.this, participant.getActivityId(), participant.getId() , jsonBody, new ApiClient.RawCallback() {; + @Override + public void onSuccess(String jsonText) { + Toast.makeText(MainActivity.this, "Ayuda material actualizada correctamente", Toast.LENGTH_SHORT).show(); + refreshActivitiesAndReload(); + } + + @Override + public void onError(String error) { + Toast.makeText(MainActivity.this, "Error al actualizar ayuda material", Toast.LENGTH_SHORT).show(); + Log.e("API", "Error al actualizar ayuda material: " + error); + } + }); + } + + /** + * + * @param participant + * @param humanHelp + */ + @Override + public void onClickOnHumanHelp(ActivityResident participant, boolean humanHelp) { + String jsonBody = "{\"recursosHumanos\": " + humanHelp + "}"; + ApiClient.patchParticipant( MainActivity.this, participant.getActivityId(), participant.getId() , jsonBody, new ApiClient.RawCallback() {; + @Override + public void onSuccess(String jsonText) { + Toast.makeText(MainActivity.this, "Ayuda humana actualizada correctamente", Toast.LENGTH_SHORT).show(); + refreshActivitiesAndReload(); + } + + @Override + public void onError(String error) { + Toast.makeText(MainActivity.this, "Error al actualizar ayuda humana", Toast.LENGTH_SHORT).show(); + Log.e("API", "Error al actualizar ayuda humana: " + error); } }); } @@ -1003,61 +1133,16 @@ public class MainActivity extends AppCompatActivity implements NavigationBarView }); } - @Override - public void onDeleteGameStat(GameStat gameStat, Game gamestatGame) { - ApiClient.deleteGameStat(MainActivity.this, gameStat.getId(), new ApiClient.RawCallback() { - @Override - public void onSuccess(String jsonText) { - Toast.makeText(MainActivity.this, "Partida eliminada correctamente", Toast.LENGTH_SHORT).show(); - refreshGameStatsAndReload(); - } - - @Override - public void onError(String error) { - Toast.makeText(MainActivity.this, "Error al eliminar partida", Toast.LENGTH_SHORT).show(); - Log.e("API", "Error al eliminar partida: " + error); - } - }); - } - - @Override - public void onTakeOutResident(Resident resident) { - ApiClient.patchTakeOutResident( MainActivity.this, resident.getId(), new ApiClient.RawCallback() { - @Override - public void onSuccess(String jsonText) { - Toast.makeText(MainActivity.this, "Residente dado de baja correctamente", Toast.LENGTH_SHORT).show(); - refreshResidentsAndReload(); - refreshGameStatsAndReload(); - } - - @Override - public void onError(String error) { - Toast.makeText(MainActivity.this, "Error al dar de baja a residente", Toast.LENGTH_SHORT).show(); - Log.e("API", "Error al eliminar residente: " + error); - } - }); - } - - @Override - public void onDeleteActivitie(Activity activity) { - ApiClient.deleteActivity(MainActivity.this, activity.getId(), new ApiClient.RawCallback() { - @Override - public void onSuccess(String jsonText) { - Toast.makeText(MainActivity.this, "Actividad eliminada correctamente", Toast.LENGTH_SHORT).show(); - refreshActivitiesAndReload(); - } - - @Override - public void onError(String error) { - Toast.makeText(MainActivity.this, "Error al eliminar actividad", Toast.LENGTH_SHORT).show(); - Log.e("API", "Error al eliminar actividad: " + error); - } - }); - } + // --------------------------------------------------------------------- LogOut listener --------------------------------------------------------------------- @Override public void onLogOutButtonClicked() { SecurePreferencesUtil.clear(MainActivity.this); loadFragment(new LoginFragment()); } + + @Override + public void onClickOnBackButton() { + reloadFragment(lastFragment); + } } \ No newline at end of file diff --git a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/activities/ActivitiesFragment.java b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/activities/ActivitiesFragment.java index 28d9bf9..fab4a86 100644 --- a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/activities/ActivitiesFragment.java +++ b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/activities/ActivitiesFragment.java @@ -22,7 +22,6 @@ import com.andresgmoran.apptrabajadores.models.ActivityResident; import com.andresgmoran.apptrabajadores.models.Resident; import com.andresgmoran.apptrabajadores.models.adapters.ActivitiesAdapter; import com.andresgmoran.apptrabajadores.ui.MainActivity; -import com.andresgmoran.apptrabajadores.ui.fragments.residentList.ResidentsListFragment; import com.google.android.material.floatingactionbutton.FloatingActionButton; import java.util.List; diff --git a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/activities/ActivityDetailFragment.java b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/activities/ActivityDetailFragment.java index c124e4c..bd2b533 100644 --- a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/activities/ActivityDetailFragment.java +++ b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/activities/ActivityDetailFragment.java @@ -1,7 +1,6 @@ package com.andresgmoran.apptrabajadores.ui.fragments.activities; import android.content.Context; -import android.graphics.Color; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -22,6 +21,7 @@ import com.andresgmoran.apptrabajadores.R; import com.andresgmoran.apptrabajadores.interfaces.IOClickOnAddParticipantListener; import com.andresgmoran.apptrabajadores.interfaces.IOClickOnParticipantListener; import com.andresgmoran.apptrabajadores.interfaces.IOnChageStateActivityListener; +import com.andresgmoran.apptrabajadores.interfaces.IOnClickOnBackButtonListener; import com.andresgmoran.apptrabajadores.models.Activity; import com.andresgmoran.apptrabajadores.models.ActivityResident; import com.andresgmoran.apptrabajadores.models.ActivityState; @@ -39,15 +39,14 @@ public class ActivityDetailFragment extends Fragment { private List participants; private List residents; - private ImageButton backButton; + private IOClickOnAddParticipantListener addParticipantListener; + private IOnChageStateActivityListener changeStateActivityListener; + private IOnClickOnBackButtonListener backButtonListener; public interface IOOnAttachListener { List getResidents(); } - private IOClickOnAddParticipantListener addParticipantListener; - private IOnChageStateActivityListener changeStateActivityListener; - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -57,62 +56,71 @@ public class ActivityDetailFragment extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + setupSwipeRefresh(view); + setupBackButton(view); + setupActivityInfo(view); + setupParticipantsStats(view); + setupAssistanceStats(view); + setupRecyclerView(view); + setupFab(view); + } + private void setupSwipeRefresh(View view) { SwipeRefreshLayout swipeRefreshLayout = view.findViewById(R.id.swipe_refresh_activity_detail); - swipeRefreshLayout.setOnRefreshListener(() -> { ((MainActivity) requireActivity()).refreshActivitiesAndReload(); swipeRefreshLayout.setRefreshing(false); }); + } + private void setupBackButton(View view) { + ImageButton backButton; backButton = view.findViewById(R.id.back_button); - backButton.setOnClickListener(v -> { - requireActivity().getSupportFragmentManager().popBackStack(); - }); + backButton.setOnClickListener(v -> backButtonListener.onClickOnBackButton()); + } + private void setupActivityInfo(View view) { TextView activityName = view.findViewById(R.id.activitie_detail_name); - - MaterialButton startEndButton = view.findViewById(R.id.btn_start_end_activity); - - if (activity.getState() == ActivityState.ABIERTO){ - startEndButton.setVisibility(View.GONE); - } else { - startEndButton.setVisibility(View.VISIBLE); - - ActivityState state = activity.getState(); - - if (state == ActivityState.CERRADO) { - startEndButton.setText("Iniciar actividad"); - startEndButton.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.purple_200)); - - startEndButton.setOnClickListener(v -> { - changeStateActivityListener.onChangeStateActivity(activity, ActivityState.EN_CURSO); - }); - - } else if (state == ActivityState.EN_CURSO) { - startEndButton.setText("Finalizar actividad"); - startEndButton.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.teal_200)); - - startEndButton.setOnClickListener(v -> { - changeStateActivityListener.onChangeStateActivity(activity, ActivityState.FINALIZADA); - }); - - } else if (state == ActivityState.FINALIZADA) { - startEndButton.setText("Actividad finalizada"); - startEndButton.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.teal_200)); - startEndButton.setEnabled(false); - } - } - - TextView description = view.findViewById(R.id.tv_description_activity_detail); - description.setText(activity.getDescription()); TextView activityDate = view.findViewById(R.id.tv_date_activity_detail); TextView activityExitTime = view.findViewById(R.id.tv_exit_time_activity_detail); + activityName.setText(activity.getName()); + description.setText(activity.getDescription()); activityDate.setText(activity.getDate().toLocalDate().toString()); activityExitTime.setText(activity.getDate().toLocalTime().toString()); + MaterialButton startEndButton = view.findViewById(R.id.btn_start_end_activity); + ActivityState state = activity.getState(); + + switch (state) { + case ABIERTO: + configureButton(startEndButton, "Cerrar actividad", R.color.purple_200, () -> + changeStateActivityListener.onChangeStateActivity(activity, ActivityState.CERRADO)); + break; + case CERRADO: + configureButton(startEndButton, "Iniciar actividad", R.color.purple_200, () -> + changeStateActivityListener.onChangeStateActivity(activity, ActivityState.EN_CURSO)); + break; + case EN_CURSO: + configureButton(startEndButton, "Finalizar actividad", R.color.teal_200, () -> + changeStateActivityListener.onChangeStateActivity(activity, ActivityState.FINALIZADA)); + break; + case FINALIZADA: + startEndButton.setText("Actividad finalizada"); + startEndButton.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.teal_200)); + startEndButton.setEnabled(false); + break; + } + } + + private void configureButton(MaterialButton button, String text, int colorRes, Runnable onClick) { + button.setText(text); + button.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), colorRes)); + button.setOnClickListener(v -> onClick.run()); + } + + private void setupParticipantsStats(View view) { List activityParticipants = new ArrayList<>(); for (ActivityResident p : participants) { if (p.getActivityId() == activity.getId()) { @@ -121,47 +129,45 @@ public class ActivityDetailFragment extends Fragment { } TextView totalParticipants = view.findViewById(R.id.tv_total_participants_activity_detail); - totalParticipants.setText(String.valueOf(activityParticipants.size())); - TextView confirmedParticipants = view.findViewById(R.id.tv_confirmed_residents); TextView notGoingParticipants = view.findViewById(R.id.tv_unconfirmed_residents); - int goingCount = 0; - int notGoingCount = 0; + + int goingCount = 0, notGoingCount = 0; for (ActivityResident p : activityParticipants) { - if (p.isAssistance()) { - goingCount++; - } else { - notGoingCount++; - } + if (p.isAssistance()) goingCount++; + else notGoingCount++; } + + totalParticipants.setText(String.valueOf(activityParticipants.size())); confirmedParticipants.setText(String.valueOf(goingCount)); notGoingParticipants.setText(String.valueOf(notGoingCount)); + } + private void setupAssistanceStats(View view) { TextView humanAssistance = view.findViewById(R.id.tv_required_human_attendance); TextView materialAssistance = view.findViewById(R.id.tv_required_material_attendance); - int humanAssistanceCount = 0; - int materialAssistanceCount = 0; - for (ActivityResident p : activityParticipants) { - if (p.isHumanHelp()) { - humanAssistanceCount++; - } else if (p.isMaterialHelp()) { - materialAssistanceCount++; + int humanCount = 0, materialCount = 0; + for (ActivityResident p : participants) { + if (p.getActivityId() == activity.getId()) { + if (p.isHumanHelp()) humanCount++; + else if (p.isMaterialHelp()) materialCount++; } } - humanAssistance.setText(String.valueOf(humanAssistanceCount)); - materialAssistance.setText(String.valueOf(materialAssistanceCount)); - - - + humanAssistance.setText(String.valueOf(humanCount)); + materialAssistance.setText(String.valueOf(materialCount)); + } + private void setupRecyclerView(View view) { RecyclerView recyclerView = view.findViewById(R.id.rv_participants); - ParticipantsAdapter participantsAdapter = new ParticipantsAdapter(requireContext() , activity, participants, residents, (IOClickOnParticipantListener) requireActivity()); - recyclerView.setAdapter(participantsAdapter); - recyclerView.setHasFixedSize(true); + ParticipantsAdapter adapter = new ParticipantsAdapter(requireContext(), activity, participants, residents, (IOClickOnParticipantListener) requireActivity()); + recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); + recyclerView.setHasFixedSize(true); + } + private void setupFab(View view) { MaterialButton fab = view.findViewById(R.id.add_participant_button); if (activity.getState() == ActivityState.CERRADO) { fab.setVisibility(View.GONE); @@ -171,7 +177,6 @@ public class ActivityDetailFragment extends Fragment { ); NestedScrollView scrollView = view.findViewById(R.id.nested_scroll_game_detail); - scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() { private int lastScrollY = 0; private boolean isButtonVisible = true; @@ -179,11 +184,9 @@ public class ActivityDetailFragment extends Fragment { @Override public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { if (scrollY > lastScrollY + 10 && isButtonVisible) { - // Scroll hacia abajo: ocultar con animación fab.animate().translationY(fab.getHeight() + 50).alpha(0.0f).setDuration(200).withEndAction(() -> fab.setVisibility(View.GONE)); isButtonVisible = false; } else if (scrollY < lastScrollY - 10 && !isButtonVisible) { - // Scroll hacia arriba: mostrar con animación fab.setVisibility(View.VISIBLE); fab.setAlpha(0f); fab.setTranslationY(fab.getHeight() + 50); @@ -198,19 +201,16 @@ public class ActivityDetailFragment extends Fragment { @Override public void onAttach(@NonNull Context context) { + super.onAttach(context); + if (getArguments() != null) { activity = (Activity) getArguments().getSerializable("activity"); participants = (List) getArguments().getSerializable("participants"); } - if (context instanceof IOOnAttachListener) { - residents = ((IOOnAttachListener) context).getResidents(); - } else { - throw new RuntimeException(context.toString() + " must implement IOOnAttachListener"); - } - + residents = ((IOOnAttachListener) context).getResidents(); addParticipantListener = (IOClickOnAddParticipantListener) context; changeStateActivityListener = (IOnChageStateActivityListener) context; - super.onAttach(context); + backButtonListener = (IOnClickOnBackButtonListener) context; } } diff --git a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/game/GameFragment.java b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/game/GameFragment.java index 74c166e..155698f 100644 --- a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/game/GameFragment.java +++ b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/game/GameFragment.java @@ -18,6 +18,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.andresgmoran.apptrabajadores.R; import com.andresgmoran.apptrabajadores.interfaces.IOClickOnGameStatsListener; +import com.andresgmoran.apptrabajadores.interfaces.IOnClickOnBackButtonListener; import com.andresgmoran.apptrabajadores.models.Game; import com.andresgmoran.apptrabajadores.models.Resident; import com.andresgmoran.apptrabajadores.models.adapters.LastGamesAdapter; @@ -33,6 +34,8 @@ public class GameFragment extends Fragment { private List residents; private Game game; + private IOnClickOnBackButtonListener backButtonListener; + private TextView gameNameTextView; private TextView numberOfGamesLastWeekTextView; private TextView totalGamesPlayedTextView; @@ -61,7 +64,7 @@ public class GameFragment extends Fragment { backButton = view.findViewById(R.id.back_button); backButton.setOnClickListener(v -> { - requireActivity().getSupportFragmentManager().popBackStack(); + backButtonListener.onClickOnBackButton(); }); List allGameStats = new ArrayList<>(); @@ -142,7 +145,9 @@ public class GameFragment extends Fragment { gameStats = (List) getArguments().getSerializable("gameStats"); residents = (List) getArguments().getSerializable("residents"); game = (Game) getArguments().getSerializable("game"); + } + backButtonListener = (IOnClickOnBackButtonListener) context; } } diff --git a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/gameDetail/GameDetailFragment.java b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/gameDetail/GameDetailFragment.java index 57339ae..a67de65 100644 --- a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/gameDetail/GameDetailFragment.java +++ b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/gameDetail/GameDetailFragment.java @@ -16,6 +16,7 @@ import androidx.fragment.app.Fragment; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.andresgmoran.apptrabajadores.R; +import com.andresgmoran.apptrabajadores.interfaces.IOnClickOnBackButtonListener; import com.andresgmoran.apptrabajadores.models.Game; import com.andresgmoran.apptrabajadores.models.Resident; import com.andresgmoran.apptrabajadores.models.User; @@ -31,6 +32,7 @@ public class GameDetailFragment extends Fragment { List getUsers(); } private IOnAddObservationListener addObservationListener; + private IOnClickOnBackButtonListener backButtonListener; private GameStat gameStat; private Resident gameStatResident; @@ -64,7 +66,7 @@ public class GameDetailFragment extends Fragment { backButton = view.findViewById(R.id.back_button); backButton.setOnClickListener(v -> { - requireActivity().getSupportFragmentManager().popBackStack(); + backButtonListener.onClickOnBackButton(); }); residentNameTextView = view.findViewById(R.id.banner_name_resident); @@ -129,11 +131,8 @@ public class GameDetailFragment extends Fragment { public void onAttach(@NonNull Context context) { super.onAttach(context); - if (context instanceof IOnAddObservationListener) { - addObservationListener = (IOnAddObservationListener) context; - } else { - throw new RuntimeException(context.toString() + " must implement IOnAddObservationListener"); - } + addObservationListener = (IOnAddObservationListener) context; + backButtonListener = (IOnClickOnBackButtonListener) context; users = addObservationListener.getUsers(); diff --git a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/home/HomeFragment.java b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/home/HomeFragment.java index 710e90f..ac2977f 100644 --- a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/home/HomeFragment.java +++ b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/home/HomeFragment.java @@ -3,17 +3,16 @@ package com.andresgmoran.apptrabajadores.ui.fragments.home; import android.content.Context; import android.graphics.Bitmap; import android.os.Bundle; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; @@ -29,9 +28,8 @@ import com.andresgmoran.apptrabajadores.models.adapters.GamesAdapter; import com.andresgmoran.apptrabajadores.models.adapters.LastGamesAdapter; import com.andresgmoran.apptrabajadores.models.adapters.ResidentsAdapter; import com.andresgmoran.apptrabajadores.models.gameStats.GameStat; -import com.andresgmoran.apptrabajadores.network.ApiClient; import com.andresgmoran.apptrabajadores.ui.MainActivity; -import com.bumptech.glide.Glide; +import com.andresgmoran.apptrabajadores.viewmodel.HomeViewModel; import java.util.ArrayList; import java.util.Collections; @@ -40,18 +38,10 @@ import java.util.List; public class HomeFragment extends Fragment { - public interface IOOnAttachListenerResidents { + public interface IOnAttachListener { List getResidents(); - } - - public interface IOOnAttachListenerGameStats { List getGameStats(); - } - - public interface IOOnAttachListenerGames { List getGames(); - } - public interface IOOnAttachListenerUser { User getActualUser(); Bitmap getActualUserImage(); } @@ -62,15 +52,14 @@ public class HomeFragment extends Fragment { private User user; private Bitmap userImageBitmap; - private TextView userNameTextView; - private RecyclerView recyclerViewLastGames; - private TextView emptyLatestGamesText; - private RecyclerView recyclerViewGames; - private TextView emptyGamesText; - private RecyclerView recyclerViewResidents; - private TextView emptyResidentsText; private ImageView userImage; + private RecyclerView recyclerViewLastGames; + private RecyclerView recyclerViewGames; + private RecyclerView recyclerViewResidents; + private TextView emptyLatestGamesText; + private TextView emptyGamesText; + private TextView emptyResidentsText; private GamesAdapter gamesAdapter; private ResidentsAdapter residentsAdapter; @@ -84,24 +73,35 @@ public class HomeFragment extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + setupSwipeRefresh(view); + setupUserInfo(view); + setupLastGamesList(view); + setupGamesList(view); + setupResidentsList(view); + setupFilterButtons(view); + } + private void setupSwipeRefresh(View view) { SwipeRefreshLayout swipeRefreshLayout = view.findViewById(R.id.swipe_refresh_home); - swipeRefreshLayout.setOnRefreshListener(() -> { ((MainActivity) requireActivity()).refreshGameStatsAndReload(); swipeRefreshLayout.setRefreshing(false); }); + } + private void setupUserInfo(View view) { userNameTextView = view.findViewById(R.id.home_user_name); - String fullName = user.getName() + " " + user.getSurnames(); - userNameTextView.setText(fullName); userImage = view.findViewById(R.id.user_image_home); + userNameTextView.setText(user.getName() + " " + user.getSurnames()); userImage.setImageBitmap(userImageBitmap); + } + private void setupLastGamesList(View view) { emptyLatestGamesText = view.findViewById(R.id.tv_lastgames_empty_home); - LastGamesAdapter lastGamesAdapter = new LastGamesAdapter(gameStats, games, residents, (IOClickOnGameStatsListener) requireActivity()); recyclerViewLastGames = view.findViewById(R.id.latestGames_recycleView_home); - recyclerViewLastGames.setAdapter(lastGamesAdapter); + + LastGamesAdapter adapter = new LastGamesAdapter(gameStats, games, residents, (IOClickOnGameStatsListener) requireActivity()); + recyclerViewLastGames.setAdapter(adapter); recyclerViewLastGames.setHasFixedSize(true); recyclerViewLastGames.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false)); @@ -112,13 +112,16 @@ public class HomeFragment extends Fragment { recyclerViewLastGames.setVisibility(View.VISIBLE); emptyLatestGamesText.setVisibility(View.GONE); } + } + private void setupGamesList(View view) { emptyGamesText = view.findViewById(R.id.tv_games_empty_home); - gamesAdapter = new GamesAdapter(games, (IOClickOnGameListener) requireActivity()); recyclerViewGames = view.findViewById(R.id.games_recycleView_home); + + gamesAdapter = new GamesAdapter(games, (IOClickOnGameListener) requireActivity()); recyclerViewGames.setAdapter(gamesAdapter); recyclerViewGames.setHasFixedSize(true); - recyclerViewGames.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); + recyclerViewGames.setLayoutManager(new LinearLayoutManager(getActivity())); if (games.isEmpty()) { recyclerViewGames.setVisibility(View.GONE); @@ -127,13 +130,16 @@ public class HomeFragment extends Fragment { recyclerViewGames.setVisibility(View.VISIBLE); emptyGamesText.setVisibility(View.GONE); } + } + private void setupResidentsList(View view) { emptyResidentsText = view.findViewById(R.id.tv_residents_empty_home); - residentsAdapter = new ResidentsAdapter(residents, (IOClickOnResidentListener) requireActivity()); recyclerViewResidents = view.findViewById(R.id.residents_recycleView_home); + + residentsAdapter = new ResidentsAdapter(residents, (IOClickOnResidentListener) requireActivity()); recyclerViewResidents.setAdapter(residentsAdapter); recyclerViewResidents.setHasFixedSize(true); - recyclerViewResidents.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); + recyclerViewResidents.setLayoutManager(new LinearLayoutManager(getActivity())); if (residents.isEmpty()) { recyclerViewResidents.setVisibility(View.GONE); @@ -142,7 +148,9 @@ public class HomeFragment extends Fragment { recyclerViewResidents.setVisibility(View.VISIBLE); emptyResidentsText.setVisibility(View.GONE); } + } + private void setupFilterButtons(View view) { View filterGamesButton = view.findViewById(R.id.filter_games_list_button); View filterResidentsButton = view.findViewById(R.id.filter_residents_list_button); @@ -153,19 +161,13 @@ public class HomeFragment extends Fragment { @Override public void onAttach(@NonNull Context context) { super.onAttach(context); + IOnAttachListener attachListener = (IOnAttachListener) context; - IOOnAttachListenerUser attachListenerActualUser = (IOOnAttachListenerUser) context; - user = attachListenerActualUser.getActualUser(); - userImageBitmap = attachListenerActualUser.getActualUserImage(); - - IOOnAttachListenerGameStats attachListenerLastGames = (IOOnAttachListenerGameStats) context; - gameStats = attachListenerLastGames.getGameStats(); - - IOOnAttachListenerResidents attachListenerResidents = (IOOnAttachListenerResidents) context; - residents = attachListenerResidents.getResidents(); - - IOOnAttachListenerGames attachListenerGames = (IOOnAttachListenerGames) context; - games = attachListenerGames.getGames(); + user = attachListener.getActualUser(); + userImageBitmap = attachListener.getActualUserImage(); + residents = attachListener.getResidents(); + games = attachListener.getGames(); + gameStats = attachListener.getGameStats(); } private void showGamesFilterDialog() { @@ -173,10 +175,7 @@ public class HomeFragment extends Fragment { new androidx.appcompat.app.AlertDialog.Builder(requireContext()) .setTitle("Filtrar juegos") - .setItems(options, (dialog, which) -> { - String selectedOption = options[which]; - filterGamesList(selectedOption); - }) + .setItems(options, (dialog, which) -> filterGamesList(options[which])) .show(); } @@ -185,10 +184,7 @@ public class HomeFragment extends Fragment { new androidx.appcompat.app.AlertDialog.Builder(requireContext()) .setTitle("Filtrar residentes") - .setItems(options, (dialog, which) -> { - String selectedOption = options[which]; - filterResidentsList(selectedOption); - }) + .setItems(options, (dialog, which) -> filterResidentsList(options[which])) .show(); } @@ -197,26 +193,16 @@ public class HomeFragment extends Fragment { switch (option) { case "A-Z": - Collections.sort(filteredList, Comparator.comparing(Game::getName)); + filteredList.sort(Comparator.comparing(Game::getName)); break; case "Z-A": - Collections.sort(filteredList, (g1, g2) -> g2.getName().compareTo(g1.getName())); + filteredList.sort((g1, g2) -> g2.getName().compareTo(g1.getName())); break; case "Más jugados": - Collections.sort(filteredList, (g1, g2) -> { - int count1 = 0; - int count2 = 0; - - for (GameStat stat : gameStats) { - if (stat.getGameId() == g1.getId()) { - count1++; - } - if (stat.getGameId() == g2.getId()) { - count2++; - } - } - - return Integer.compare(count2, count1); // Mayor a menor + filteredList.sort((g1, g2) -> { + long count1 = gameStats.stream().filter(stat -> stat.getGameId() == g1.getId()).count(); + long count2 = gameStats.stream().filter(stat -> stat.getGameId() == g2.getId()).count(); + return Long.compare(count2, count1); }); break; } @@ -230,13 +216,13 @@ public class HomeFragment extends Fragment { switch (option) { case "A-Z": - Collections.sort(filteredList, Comparator.comparing(Resident::getName)); + filteredList.sort(Comparator.comparing(Resident::getName)); break; case "Z-A": - Collections.sort(filteredList, (r1, r2) -> r2.getName().compareTo(r1.getName())); + filteredList.sort((r1, r2) -> r2.getName().compareTo(r1.getName())); break; case "Fecha de nacimiento": - Collections.sort(filteredList, Comparator.comparing(Resident::getBirthDate)); + filteredList.sort(Comparator.comparing(Resident::getBirthDate)); break; } diff --git a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/resident/ResidentFragment.java b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/resident/ResidentFragment.java index 9812b56..c28e9f5 100644 --- a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/resident/ResidentFragment.java +++ b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/resident/ResidentFragment.java @@ -20,6 +20,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.andresgmoran.apptrabajadores.R; import com.andresgmoran.apptrabajadores.interfaces.IOClickOnGameStatsListener; +import com.andresgmoran.apptrabajadores.interfaces.IOnClickOnBackButtonListener; import com.andresgmoran.apptrabajadores.models.Game; import com.andresgmoran.apptrabajadores.models.Resident; import com.andresgmoran.apptrabajadores.models.adapters.LastGamesAdapter; @@ -45,6 +46,8 @@ public class ResidentFragment extends Fragment { private TextView tvLastGamesEmpty; private TextView tvStatsEmpty; + private IOnClickOnBackButtonListener backButtonListener; + @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -70,7 +73,7 @@ public class ResidentFragment extends Fragment { backButton = banner.findViewById(R.id.back_button); backButton.setOnClickListener(v -> { - requireActivity().getSupportFragmentManager().popBackStack(); + backButtonListener.onClickOnBackButton(); }); residentName = banner.findViewById(R.id.banner_name_game); @@ -268,6 +271,8 @@ public class ResidentFragment extends Fragment { games = (ArrayList) args.getSerializable("games"); gameStats = (ArrayList) args.getSerializable("gameStats"); } + + backButtonListener = (IOnClickOnBackButtonListener) context; } } diff --git a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/residentList/ResidentsListFragment.java b/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/residentList/ResidentsListFragment.java deleted file mode 100644 index 9b1e7c5..0000000 --- a/AppTrabajadores/app/src/main/java/com/andresgmoran/apptrabajadores/ui/fragments/residentList/ResidentsListFragment.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.andresgmoran.apptrabajadores.ui.fragments.residentList; - -import android.content.Context; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.andresgmoran.apptrabajadores.R; -import com.andresgmoran.apptrabajadores.interfaces.IOClickOnResidentListener; -import com.andresgmoran.apptrabajadores.models.Resident; -import com.andresgmoran.apptrabajadores.models.adapters.ResidentsAdapter; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -public class ResidentsListFragment extends Fragment { - - private ResidentsAdapter residentsAdapter; - private RecyclerView recyclerViewResidents; - - public interface IOOnAttachListener{ - List getResidents(); - } - - private List residents; - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate( R.layout.fragment_residents_list, container, false); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - residentsAdapter = new ResidentsAdapter(residents, (IOClickOnResidentListener) requireActivity()); - recyclerViewResidents = view.findViewById(R.id.residents_recycleView); - recyclerViewResidents.setAdapter(residentsAdapter); - recyclerViewResidents.setHasFixedSize(true); - recyclerViewResidents.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); - - View filterResidentsButton = view.findViewById(R.id.filter_residents_list_button); - - filterResidentsButton.setOnClickListener(v -> showResidentsFilterDialog()); - } - - private void showResidentsFilterDialog() { - String[] options = {"A-Z", "Z-A", "Fecha de nacimiento"}; - - new androidx.appcompat.app.AlertDialog.Builder(requireContext()) - .setTitle("Filtrar residentes") - .setItems(options, (dialog, which) -> { - String selectedOption = options[which]; - filterResidentsList(selectedOption); - }) - .show(); - } - - private void filterResidentsList(String option) { - List filteredList = new ArrayList<>(residents); - - switch (option) { - case "A-Z": - Collections.sort(filteredList, Comparator.comparing(Resident::getName)); - break; - case "Z-A": - Collections.sort(filteredList, (r1, r2) -> r2.getName().compareTo(r1.getName())); - break; - case "Fecha de nacimiento": - Collections.sort(filteredList, Comparator.comparing(Resident::getBirthDate)); - break; - } - - residentsAdapter.updateData(filteredList); - recyclerViewResidents.scrollToPosition(0); - } - - @Override - public void onAttach(@NonNull Context context) { - super.onAttach(context); - ResidentsListFragment.IOOnAttachListener attachListener = (ResidentsListFragment.IOOnAttachListener) context; - residents = attachListener.getResidents(); - } -} diff --git a/AppTrabajadores/app/src/main/res/drawable/icon_background.xml b/AppTrabajadores/app/src/main/res/drawable/icon_background.xml new file mode 100644 index 0000000..ca3826a --- /dev/null +++ b/AppTrabajadores/app/src/main/res/drawable/icon_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AppTrabajadores/app/src/main/res/layout/fragment_resident.xml b/AppTrabajadores/app/src/main/res/layout/fragment_resident.xml index e0391bb..56d5fdd 100644 --- a/AppTrabajadores/app/src/main/res/layout/fragment_resident.xml +++ b/AppTrabajadores/app/src/main/res/layout/fragment_resident.xml @@ -45,7 +45,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:fontFamily="@font/assistant_bold" - android:text="Últimas partidas" + android:text="@string/last_games_list_title" android:textColor="#324F5E" android:textSize="20sp" /> @@ -77,7 +77,7 @@ android:layout_height="wrap_content" android:layout_marginTop="5dp" android:fontFamily="@font/assistant_semibold" - android:text="No hay partidas disponibles" + android:text="@string/no_last_games_available_text" android:textColor="#96A7AF" android:visibility="gone" app:layout_constraintEnd_toEndOf="@+id/linearLayout2" @@ -91,7 +91,7 @@ android:layout_marginHorizontal="20dp" android:layout_marginTop="20dp" android:fontFamily="@font/assistant_bold" - android:text="Estadísticas" + android:text="@string/stats_title" android:textColor="#324F5E" android:textSize="20sp" app:layout_constraintEnd_toEndOf="parent" @@ -105,7 +105,7 @@ android:layout_height="wrap_content" android:layout_marginTop="5dp" android:fontFamily="@font/assistant_semibold" - android:text="No hay estadisticas disponibles" + android:text="@string/no_stats_available_text" android:textColor="#96A7AF" android:visibility="gone" app:layout_constraintEnd_toEndOf="@+id/textView16" diff --git a/AppTrabajadores/app/src/main/res/layout/fragment_residents_list.xml b/AppTrabajadores/app/src/main/res/layout/fragment_residents_list.xml deleted file mode 100644 index adeac01..0000000 --- a/AppTrabajadores/app/src/main/res/layout/fragment_residents_list.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/AppTrabajadores/app/src/main/res/menu/bottom_nav_menu.xml b/AppTrabajadores/app/src/main/res/menu/bottom_nav_menu.xml index b5d7495..77dcfa5 100644 --- a/AppTrabajadores/app/src/main/res/menu/bottom_nav_menu.xml +++ b/AppTrabajadores/app/src/main/res/menu/bottom_nav_menu.xml @@ -6,11 +6,6 @@ android:icon="@drawable/ic_home_black_24dp" android:title="@string/title_home" /> - - + + + + \ No newline at end of file diff --git a/AppTrabajadores/app/src/main/res/mipmap-anydpi-v26/icon_round.xml b/AppTrabajadores/app/src/main/res/mipmap-anydpi-v26/icon_round.xml new file mode 100644 index 0000000..c1c1a28 --- /dev/null +++ b/AppTrabajadores/app/src/main/res/mipmap-anydpi-v26/icon_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/AppTrabajadores/app/src/main/res/mipmap-hdpi/icon.webp b/AppTrabajadores/app/src/main/res/mipmap-hdpi/icon.webp new file mode 100644 index 0000000..372d0bd Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-hdpi/icon.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-hdpi/icon_foreground.webp b/AppTrabajadores/app/src/main/res/mipmap-hdpi/icon_foreground.webp new file mode 100644 index 0000000..63b3787 Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-hdpi/icon_foreground.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-hdpi/icon_round.webp b/AppTrabajadores/app/src/main/res/mipmap-hdpi/icon_round.webp new file mode 100644 index 0000000..51840f9 Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-hdpi/icon_round.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-mdpi/icon.webp b/AppTrabajadores/app/src/main/res/mipmap-mdpi/icon.webp new file mode 100644 index 0000000..ca167be Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-mdpi/icon.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-mdpi/icon_foreground.webp b/AppTrabajadores/app/src/main/res/mipmap-mdpi/icon_foreground.webp new file mode 100644 index 0000000..f1bb23c Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-mdpi/icon_foreground.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-mdpi/icon_round.webp b/AppTrabajadores/app/src/main/res/mipmap-mdpi/icon_round.webp new file mode 100644 index 0000000..09c1a42 Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-mdpi/icon_round.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-xhdpi/icon.webp b/AppTrabajadores/app/src/main/res/mipmap-xhdpi/icon.webp new file mode 100644 index 0000000..edcce27 Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-xhdpi/icon.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-xhdpi/icon_foreground.webp b/AppTrabajadores/app/src/main/res/mipmap-xhdpi/icon_foreground.webp new file mode 100644 index 0000000..d313838 Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-xhdpi/icon_foreground.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-xhdpi/icon_round.webp b/AppTrabajadores/app/src/main/res/mipmap-xhdpi/icon_round.webp new file mode 100644 index 0000000..f067112 Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-xhdpi/icon_round.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-xxhdpi/icon.webp b/AppTrabajadores/app/src/main/res/mipmap-xxhdpi/icon.webp new file mode 100644 index 0000000..2815fd8 Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-xxhdpi/icon.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-xxhdpi/icon_foreground.webp b/AppTrabajadores/app/src/main/res/mipmap-xxhdpi/icon_foreground.webp new file mode 100644 index 0000000..4912470 Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-xxhdpi/icon_foreground.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-xxhdpi/icon_round.webp b/AppTrabajadores/app/src/main/res/mipmap-xxhdpi/icon_round.webp new file mode 100644 index 0000000..6f3fe19 Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-xxhdpi/icon_round.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-xxxhdpi/icon.webp b/AppTrabajadores/app/src/main/res/mipmap-xxxhdpi/icon.webp new file mode 100644 index 0000000..68c681c Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-xxxhdpi/icon.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-xxxhdpi/icon_foreground.webp b/AppTrabajadores/app/src/main/res/mipmap-xxxhdpi/icon_foreground.webp new file mode 100644 index 0000000..2ff66f7 Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-xxxhdpi/icon_foreground.webp differ diff --git a/AppTrabajadores/app/src/main/res/mipmap-xxxhdpi/icon_round.webp b/AppTrabajadores/app/src/main/res/mipmap-xxxhdpi/icon_round.webp new file mode 100644 index 0000000..5df04f8 Binary files /dev/null and b/AppTrabajadores/app/src/main/res/mipmap-xxxhdpi/icon_round.webp differ diff --git a/AppTrabajadores/app/src/main/res/values-en/strings.xml b/AppTrabajadores/app/src/main/res/values-en/strings.xml new file mode 100644 index 0000000..77b89bd --- /dev/null +++ b/AppTrabajadores/app/src/main/res/values-en/strings.xml @@ -0,0 +1,12 @@ + + + App Trabajadores + Home + Dashboard + Notifications + Residents + Last games + There are no games available + Stats + No stats available + \ No newline at end of file diff --git a/AppTrabajadores/app/src/main/res/values/strings.xml b/AppTrabajadores/app/src/main/res/values/strings.xml index 4a4a449..9185ef9 100644 --- a/AppTrabajadores/app/src/main/res/values/strings.xml +++ b/AppTrabajadores/app/src/main/res/values/strings.xml @@ -3,4 +3,10 @@ Home Dashboard Notifications + Residentes + Últimas partidas\n + No hay partidas disponibles + Estadísticas + No hay estadisticas disponibles + \ No newline at end of file