Tesis 1.0.0
Loading...
Searching...
No Matches
HomeFragment.java
Go to the documentation of this file.
1package com.example.food_front;
2
3import android.content.Intent;
4import android.graphics.drawable.Drawable;
5import android.net.Uri;
6import android.os.Bundle;
7import android.util.Log;
8import android.view.LayoutInflater;
9import android.view.View;
10import android.view.ViewGroup;
11import android.widget.Button;
12import android.widget.ImageView;
13import android.widget.TextView;
14
15import androidx.annotation.NonNull;
16import androidx.annotation.Nullable;
17import androidx.fragment.app.Fragment;
18import androidx.fragment.app.FragmentManager;
19import androidx.fragment.app.FragmentTransaction;
20import androidx.recyclerview.widget.LinearLayoutManager;
21import androidx.recyclerview.widget.RecyclerView;
22
23import com.android.volley.Request;
24import com.android.volley.Response;
25import com.android.volley.toolbox.StringRequest;
26import com.android.volley.toolbox.Volley;
27import com.bumptech.glide.Glide;
28import com.bumptech.glide.load.DataSource;
29import com.bumptech.glide.load.engine.GlideException;
30import com.bumptech.glide.request.RequestListener;
31import com.bumptech.glide.request.target.Target;
32import com.example.food_front.adapters.ProductoAdapter;
33import com.example.food_front.models.Producto;
34import com.example.food_front.utils.ProfileManager;
35import com.example.food_front.utils.SessionManager;
36import com.google.android.material.floatingactionbutton.FloatingActionButton;
37
38import org.json.JSONArray;
39import org.json.JSONException;
40import org.json.JSONObject;
41
42import java.util.ArrayList;
43import java.util.List;
44
45import de.hdodenhof.circleimageview.CircleImageView;
46
47public class HomeFragment extends Fragment {
48 private TextView tvName;
49 private CircleImageView profileImage;
50 private ProfileManager profileManager;
51 private RecyclerView recyclerView;
52 private ProductoAdapter adapter;
53 private List<Producto> productList;
54
55 private static final String TAG = "HomeFragment";
56
57 @Nullable
58 @Override
59 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
60 View view = inflater.inflate(R.layout.fragment_home, container, false);
61
62 // Inicializar vistas
63 tvName = view.findViewById(R.id.txtUser);
64 profileImage = view.findViewById(R.id.profileImage);
65 Button button1 = view.findViewById(R.id.btn1);
66 Button button2 = view.findViewById(R.id.btn);
67 Button button3 = view.findViewById(R.id.btn3);
68 Button button4 = view.findViewById(R.id.btn4);
69 ImageView imageView1 = view.findViewById(R.id.imageView3);
70 ImageView imageView2 = view.findViewById(R.id.imageView4);
71 FloatingActionButton btnWebsite = view.findViewById(R.id.btnWebsite);
72
73 // Inicializar RecyclerView para productos
74 recyclerView = view.findViewById(R.id.recyclerview_productos_home);
75 recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
76
77 // Inicializar lista de productos y adaptador
78 productList = new ArrayList<>();
79 adapter = new ProductoAdapter(productList, new ProductoAdapter.OnProductoClickListener() {
80 @Override
81 public void onAgregarCarritoClick(Producto producto) {
82 agregarProductoAlCarrito(producto.getIdProducto());
83 }
84 });
85
86 recyclerView.setAdapter(adapter);
87
88 // Configurar el onClick para el botón de navegación web
89 btnWebsite.setOnClickListener(v -> {
90 String url = "https://ispcfood.netlify.app/";
91 Intent intent = new Intent(Intent.ACTION_VIEW);
92 intent.setData(Uri.parse(url));
93 startActivity(intent);
94 });
95
96 profileManager = new ProfileManager(requireContext());
97 SessionManager sessionManager = new SessionManager(requireContext());
98
99 // Mostrar el nombre del usuario e imagen de perfil
100 mostrarNombreUsuario();
101 cargarImagenPerfil();
102 // ...NO cargar productos automáticamente...
103 // cargarProductos(0); // <--- QUITADO para que Home no muestre la carta por defecto
104
105 // Modificamos los listeners para cargar productos en el mismo fragmento
106 button1.setOnClickListener(v -> navegarAProductosConFiltro(3)); // Hamburguesas id 3
107 button2.setOnClickListener(v -> navegarAProductosConFiltro(1)); // Empanadas id 1
108 button3.setOnClickListener(v -> navegarAProductosConFiltro(0)); // Todos los productos
109 button4.setOnClickListener(v -> navegarAProductosConFiltro(2)); // Lomitos id 2
110 imageView1.setOnClickListener(v -> navegarAProductosConFiltro(3)); // Hamburguesas id 3
111 imageView2.setOnClickListener(v -> navegarAProductosConFiltro(2)); // Lomitos id 2
112
113 return view;
114 }
115
116 private void mostrarNombreUsuario() {
117 String nombreGuardado = profileManager.getName();
118 if (nombreGuardado != null) {
119 tvName.setText(getString(R.string.bienvenido_usuario, nombreGuardado));
120 } else {
121 tvName.setText(R.string.usuario);
122 }
123 }
124
125 private void cargarImagenPerfil() {
126 String baseUrl = profileManager.getProfileImageUrl(); // Obtener URL base sin timestamp
127 String imageUrl = profileManager.getProfileImageUrlWithTimestamp(); // URL con timestamp para Glide
128
129 Log.d(TAG, "URL base recuperada: " + baseUrl);
130 Log.d(TAG, "URL con timestamp: " + imageUrl);
131
132 if (baseUrl != null && !baseUrl.isEmpty()) {
133 // Limpiar toda caché anterior
134 com.example.food_front.utils.ImageCacheManager.clearGlideCache(requireContext());
135
136 // Descargar la imagen directamente sin usar Glide
137 new Thread(() -> {
138 try {
139 // Descargar la imagen directamente
140 java.net.URL url = new java.net.URL(baseUrl);
141 java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
142 connection.setDoInput(true);
143 connection.setUseCaches(false); // Evitar caché
144 connection.setRequestProperty("Cache-Control", "no-cache, no-store, must-revalidate");
145 connection.setRequestProperty("Pragma", "no-cache");
146 connection.connect();
147
148 final android.graphics.Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(connection.getInputStream());
149
150 // Actualizar UI en hilo principal
151 if (getActivity() != null && !getActivity().isFinishing()) {
152 getActivity().runOnUiThread(() -> {
153 if (bitmap != null) {
154 profileImage.setImageBitmap(bitmap);
155 Log.d(TAG, "Imagen cargada exitosamente con descarga directa");
156 } else {
157 // Si falla, intentar con Glide como respaldo
158 cargarImagenConGlide(imageUrl);
159 }
160 });
161 }
162 } catch (Exception e) {
163 Log.e(TAG, "Error al descargar directamente: " + e.getMessage());
164 // En caso de error, intentar con Glide
165 if (getActivity() != null && !getActivity().isFinishing()) {
166 getActivity().runOnUiThread(() -> cargarImagenConGlide(imageUrl));
167 }
168 }
169 }).start();
170 } else {
171 Log.d(TAG, "No hay URL de imagen, usando imagen predeterminada");
172 // Usar imagen predeterminada
173 profileImage.setImageResource(R.drawable.default_profile);
174 }
175 }
176
177 private void cargarImagenConGlide(String imageUrl) {
178 // Usar Glide como método alternativo
179 Glide.with(requireContext())
180 .load(imageUrl)
181 .skipMemoryCache(true)
182 .diskCacheStrategy(com.bumptech.glide.load.engine.DiskCacheStrategy.NONE)
183 .placeholder(R.drawable.default_profile)
184 .error(R.drawable.default_profile)
185 .listener(new RequestListener<Drawable>() {
186 @Override
187 public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model,
188 @NonNull Target<Drawable> target, boolean isFirstResource) {
189 Log.e(TAG, "Error al cargar la imagen: " + e);
190 return false;
191 }
192
193 @Override
194 public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model,
195 @NonNull Target<Drawable> target,
196 @NonNull DataSource dataSource,
197 boolean isFirstResource) {
198 Log.d(TAG, "Imagen cargada exitosamente desde: " + model);
199 return false;
200 }
201 })
202 .into(profileImage);
203 }
204
205 // Método para actualizar la imagen de perfil desde otro fragmento
206 public void actualizarImagenPerfil(String url) {
207 if (profileImage != null && url != null && !url.isEmpty()) {
208 // Limpiar la caché primero
209 com.example.food_front.utils.ImageCacheManager.clearGlideCache(requireContext());
210
211 String imageUrlWithTimestamp = url + "?nocache=" + Math.random() + "&t=" + System.currentTimeMillis();
212 Log.d(TAG, "Actualizando imagen desde otro fragmento: " + imageUrlWithTimestamp);
213
214 // Forzar la descarga directa de la imagen sin usar Glide
215 new Thread(() -> {
216 try {
217 // Descargar la imagen directamente
218 java.net.URL url1 = new java.net.URL(url);
219 final android.graphics.Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(url1.openConnection().getInputStream());
220
221 // Actualizar UI en el hilo principal
222 if (getActivity() != null && !getActivity().isFinishing()) {
223 getActivity().runOnUiThread(() -> {
224 if (bitmap != null) {
225 // Actualizar la ImageView con el bitmap descargado
226 profileImage.setImageBitmap(bitmap);
227 Log.d(TAG, "Imagen en HomeFragment actualizada directamente con Bitmap");
228 } else {
229 // Si falla, intentar con Glide como respaldo
230 Glide.with(requireContext())
231 .load(imageUrlWithTimestamp)
232 .skipMemoryCache(true)
233 .diskCacheStrategy(com.bumptech.glide.load.engine.DiskCacheStrategy.NONE)
234 .placeholder(R.drawable.default_profile)
235 .error(R.drawable.default_profile)
236 .into(profileImage);
237 }
238 });
239 }
240 } catch (Exception e) {
241 Log.e(TAG, "Error al descargar directamente en HomeFragment: " + e.getMessage());
242 // Si falla, intentar con Glide como respaldo en el hilo principal
243 if (getActivity() != null && !getActivity().isFinishing()) {
244 getActivity().runOnUiThread(() -> {
245 Glide.with(requireContext())
246 .load(imageUrlWithTimestamp)
247 .skipMemoryCache(true)
248 .diskCacheStrategy(com.bumptech.glide.load.engine.DiskCacheStrategy.NONE)
249 .placeholder(R.drawable.default_profile)
250 .error(R.drawable.default_profile)
251 .into(profileImage);
252 });
253 }
254 }
255 }).start();
256 }
257 }
258
259 // Método para cargar productos según la categoría
260 private void cargarProductos(int categoriaId) {
261 String url = "https://backmobile1.onrender.com/api/producto/";
262
263 StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
264 response -> {
265 try {
266 // Parsear el JSON
267 JSONArray jsonArray = new JSONArray(response);
268 productList.clear();
269
270 for (int i = 0; i < jsonArray.length(); i++) {
271 JSONObject jsonObject = jsonArray.getJSONObject(i);
272
273 // Obtener los detalles del producto desde el JSON
274 int id_producto = jsonObject.getInt("id_producto");
275 String nombre_producto = jsonObject.getString("nombre_producto");
276 String descripcion = jsonObject.getString("descripcion");
277 double precio = jsonObject.getDouble("precio");
278 String imagenUrl = jsonObject.getString("imageURL");
279 int id_categoria = jsonObject.has("id_categoria") ? jsonObject.getInt("id_categoria") : 0;
280
281 // Filtrar por categoría si corresponde
282 if (categoriaId == 0 || id_categoria == categoriaId) {
283 Producto producto = new Producto(id_producto, nombre_producto, descripcion, precio, imagenUrl, id_categoria);
284 productList.add(producto); // Añadir a la lista
285 }
286 }
287
288 // Notificar al adaptador que los datos han cambiado
289 adapter.notifyDataSetChanged();
290
291 } catch (JSONException e) {
292 e.printStackTrace();
293 Log.e(TAG, "Error al parsear el JSON: " + e.getMessage());
294 }
295 }, error -> {
296 Log.e(TAG, "Error en la solicitud: " + error.getMessage());
297 }
298 );
299
300 // Añadir la solicitud a la cola
301 Volley.newRequestQueue(requireContext()).add(stringRequest);
302 }
303
304 // Método para agregar productos al carrito
305 private void agregarProductoAlCarrito(int idProducto) {
306 String url = "https://backmobile1.onrender.com/appCART/agregar/" + idProducto + "/";
307
308 SessionManager sessionManager = new SessionManager(getContext());
309 String token = sessionManager.getToken();
310 Log.d("AuthToken", "Token usado en la solicitud: " + token);
311
312 if (token != null) {
313 StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
314 response -> {
315 // Maneja la respuesta aquí
316 Log.d(TAG, "Producto agregado al carrito: " + response);
317 android.widget.Toast.makeText(getContext(), "Producto agregado al carrito", android.widget.Toast.LENGTH_SHORT).show();
318 },
319 error -> {
320 // Maneja el error aquí
321 Log.e(TAG, "Error al agregar al carrito: " + error.getMessage());
322 if (error.networkResponse != null) {
323 Log.e(TAG, "Código de respuesta: " + error.networkResponse.statusCode);
324 }
325 android.widget.Toast.makeText(getContext(), "Error al agregar producto al carrito", android.widget.Toast.LENGTH_SHORT).show();
326 }) {
327 @Override
328 public java.util.Map<String, String> getHeaders() {
329 java.util.Map<String, String> headers = new java.util.HashMap<>();
330 headers.put("Authorization", "Bearer " + token);
331 return headers;
332 }
333
334 @Override
335 protected java.util.Map<String, String> getParams() {
336 java.util.Map<String, String> params = new java.util.HashMap<>();
337 params.put("direccion", "casa"); // Dirección hardcodeada
338 params.put("cantidad", "1"); // Cantidad fija
339 return params;
340 }
341 };
342
343 // Añadir la solicitud a la cola
344 Volley.newRequestQueue(getContext()).add(stringRequest);
345 } else {
346 // Maneja el caso en que no hay token
347 android.widget.Toast.makeText(getContext(), "Debes iniciar sesión para agregar productos al carrito", android.widget.Toast.LENGTH_SHORT).show();
348 }
349 }
350
351 @Override
352 public void onResume() {
353 super.onResume();
354 // Recargar imagen de perfil del servidor
355 reloadProfileDataIfNeeded();
356 }
357
358 private void reloadProfileDataIfNeeded() {
359 // Verificar si han pasado más de 5 minutos desde la última carga
360 long lastUpdated = profileManager.getLastImageUpdate();
361 long now = System.currentTimeMillis();
362
363 if (now - lastUpdated > 5 * 60 * 1000) { // 5 minutos
364 Log.d(TAG, "Han pasado más de 5 minutos, recargando datos del perfil");
365 cargarImagenPerfil(); // Esto ya usa la URL con timestamp para forzar recarga
366 }
367 }
368
369 @Override
370 public void onStart() {
371 super.onStart();
372 // Ya no usamos BroadcastReceiver
373 }
374
375 @Override
376 public void onStop() {
377 super.onStop();
378 // Ya no necesitamos desregistrar nada
379 }
380
381 // Nueva función para navegar a ProductsFragment con filtro
382 private void navegarAProductosConFiltro(int categoriaId) {
383 ProductsFragment productsFragment = new ProductsFragment();
384 Bundle args = new Bundle();
385 args.putInt("categoria_id", categoriaId);
386 productsFragment.setArguments(args);
387 requireActivity().getSupportFragmentManager()
388 .beginTransaction()
389 .replace(R.id.fragment_container_view, productsFragment)
390 .addToBackStack(null)
391 .commit();
392 }
393}
View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)