DynamicLoader.tsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import { useState, useEffect } from "react";
  2. import { Loader2, Bot, Clock, Wifi, Coffee } from "lucide-react";
  3. interface LoadingState {
  4. message: string;
  5. icon: React.ReactNode;
  6. duration: number; // en segundos
  7. }
  8. const loadingStates: LoadingState[] = [
  9. {
  10. message: "Asistente escribiendo...",
  11. icon: <Loader2 className="w-4 h-4 animate-spin" />,
  12. duration: 4
  13. },
  14. {
  15. message: "Analizando tu consulta...",
  16. icon: <Bot className="w-4 h-4 animate-pulse" />,
  17. duration: 4
  18. },
  19. {
  20. message: "Preparando tu respuesta...",
  21. icon: <Wifi className="w-4 h-4 animate-pulse" />,
  22. duration: 4
  23. },
  24. {
  25. message: "Casi listo...",
  26. icon: <Coffee className="w-4 h-4 animate-bounce" />,
  27. duration: 8
  28. }
  29. ];
  30. export const DynamicLoader = () => {
  31. const [currentStateIndex, setCurrentStateIndex] = useState(0);
  32. const [elapsedTime, setElapsedTime] = useState(0);
  33. useEffect(() => {
  34. const interval = setInterval(() => {
  35. setElapsedTime(prev => {
  36. const newTime = prev + 1;
  37. // Calcular el tiempo acumulado hasta el estado actual
  38. let accumulatedTime = 0;
  39. for (let i = 0; i <= currentStateIndex; i++) {
  40. accumulatedTime += loadingStates[i].duration;
  41. }
  42. // Si hemos superado el tiempo del estado actual, cambiar al siguiente
  43. if (newTime >= accumulatedTime && currentStateIndex < loadingStates.length - 1) {
  44. setCurrentStateIndex(prev => prev + 1);
  45. }
  46. return newTime;
  47. });
  48. }, 1000);
  49. return () => clearInterval(interval);
  50. }, [currentStateIndex]);
  51. // Reset cuando el componente se monta
  52. useEffect(() => {
  53. setCurrentStateIndex(0);
  54. setElapsedTime(0);
  55. }, []);
  56. const currentState = loadingStates[currentStateIndex] || loadingStates[0];
  57. return (
  58. <div className="flex justify-start">
  59. <div className="bg-muted text-foreground px-4 py-3 rounded-2xl max-w-xs">
  60. <div className="flex items-center space-x-2">
  61. {currentState.icon}
  62. <span className="text-sm">{currentState.message}</span>
  63. </div>
  64. {elapsedTime > 10 && (
  65. <div className="text-xs text-muted-foreground mt-1">
  66. Tiempo transcurrido: {elapsedTime}s
  67. </div>
  68. )}
  69. </div>
  70. </div>
  71. );
  72. };