From 5cc27f852b02446659e0ab85305916c9f5e5a5f0 Mon Sep 17 00:00:00 2001
From: Ariel Costas Guerrero <ariel@costas.dev>
Date: Wed, 6 Aug 2025 00:12:19 +0200
Subject: feat: Implement pull-to-refresh functionality across various
 components

- Added `PullToRefresh` component to enable pull-to-refresh behavior in `StopList` and `Estimates` pages.
- Integrated `usePullToRefresh` hook to manage pull-to-refresh state and actions.
- Created `UpdateNotification` component to inform users of available updates from the service worker.
- Enhanced service worker management with `ServiceWorkerManager` class for better update handling and caching strategies.
- Updated CSS styles for new components and improved layout for better user experience.
- Refactored API caching logic in service worker to handle multiple endpoints and dynamic cache expiration.
- Added auto-refresh functionality for estimates data to keep information up-to-date.
---
 src/frontend/app/components/UpdateNotification.tsx | 63 ++++++++++++++++++++++
 1 file changed, 63 insertions(+)
 create mode 100644 src/frontend/app/components/UpdateNotification.tsx

(limited to 'src/frontend/app/components/UpdateNotification.tsx')

diff --git a/src/frontend/app/components/UpdateNotification.tsx b/src/frontend/app/components/UpdateNotification.tsx
new file mode 100644
index 0000000..e07ee74
--- /dev/null
+++ b/src/frontend/app/components/UpdateNotification.tsx
@@ -0,0 +1,63 @@
+import { useState, useEffect } from "react";
+import { Download, X } from "lucide-react";
+import { swManager } from "../utils/serviceWorkerManager";
+import "./UpdateNotification.css";
+
+export function UpdateNotification() {
+  const [showUpdate, setShowUpdate] = useState(false);
+  const [isUpdating, setIsUpdating] = useState(false);
+
+  useEffect(() => {
+    swManager.onUpdate(() => {
+      setShowUpdate(true);
+    });
+  }, []);
+
+  const handleUpdate = async () => {
+    setIsUpdating(true);
+    swManager.activateUpdate();
+    
+    // Wait for the page to reload
+    setTimeout(() => {
+      window.location.reload();
+    }, 500);
+  };
+
+  const handleDismiss = () => {
+    setShowUpdate(false);
+  };
+
+  if (!showUpdate) return null;
+
+  return (
+    <div className="update-notification">
+      <div className="update-content">
+        <div className="update-icon">
+          <Download size={20} />
+        </div>
+        <div className="update-text">
+          <div className="update-title">Nueva versión disponible</div>
+          <div className="update-description">
+            Actualiza para obtener las últimas mejoras
+          </div>
+        </div>
+        <div className="update-actions">
+          <button
+            className="update-button"
+            onClick={handleUpdate}
+            disabled={isUpdating}
+          >
+            {isUpdating ? "Actualizando..." : "Actualizar"}
+          </button>
+          <button
+            className="update-dismiss"
+            onClick={handleDismiss}
+            aria-label="Cerrar notificación"
+          >
+            <X size={16} />
+          </button>
+        </div>
+      </div>
+    </div>
+  );
+}
-- 
cgit v1.3

