Rafael Lopez

site

1 +<script>
2 + let { size = 40, color = 'currentColor' } = $props();
3 +</script>
4 +
5 +<svg
6 + fill={color}
7 + viewBox="0 -10 40 28"
8 + xmlns="http://www.w3.org/2000/svg"
9 + width={size}
10 + height={size * 0.7}
11 + class="spinner"
12 +>
13 + <circle cx="8" cy="12" r="3" class="first"/>
14 + <circle cx="16" cy="12" r="3"/>
15 + <circle cx="24" cy="12" r="3"/>
16 + <circle cx="32" cy="12" r="3" class="second"/>
17 +</svg>
18 +
19 +<style>
20 + @keyframes swing {
21 + 0% {
22 + transform: rotate(0deg);
23 + animation-timing-function: ease-out;
24 + }
25 + 25% {
26 + transform: rotate(50deg);
27 + animation-timing-function: ease-in;
28 + }
29 + 50% {
30 + transform: rotate(0deg);
31 + animation-timing-function: linear;
32 + }
33 + }
34 +
35 + @keyframes swing2 {
36 + 0% {
37 + transform: rotate(0deg);
38 + animation-timing-function: linear;
39 + }
40 + 50% {
41 + transform: rotate(0deg);
42 + animation-timing-function: ease-out;
43 + }
44 + 75% {
45 + transform: rotate(-50deg);
46 + animation-timing-function: ease-in;
47 + }
48 + }
49 +
50 + .spinner .first {
51 + animation: swing 1.2s linear infinite;
52 + transform-origin: center top;
53 + }
54 +
55 + .spinner .second {
56 + animation: swing2 1.2s linear infinite;
57 + transform-origin: center top;
58 + }
59 +</style>
1 +/**
2 + * Cache store for clasificador data
3 + * Persists data in memory to avoid reloading on navigation
4 + */
5 +import { writable } from 'svelte/store';
6 +
7 +// Cache structure
8 +const createClasificadorCache = () => {
9 + const { subscribe, set, update } = writable({
10 + objetoGasto: {
11 + allItems: null,
12 + grupos: null,
13 + entities: null,
14 + availableYears: null,
15 + lastFetched: null
16 + }
17 + });
18 +
19 + return {
20 + subscribe,
21 +
22 + // Set all clasificador objeto data
23 + setObjetoGasto: (data) => {
24 + update(cache => ({
25 + ...cache,
26 + objetoGasto: {
27 + ...data,
28 + lastFetched: Date.now()
29 + }
30 + }));
31 + },
32 +
33 + // Get cached data if valid (less than 5 minutes old)
34 + getObjetoGasto: (currentCache) => {
35 + const cache = currentCache.objetoGasto;
36 + if (!cache.lastFetched) return null;
37 +
38 + // Cache valid for 5 minutes
39 + const isValid = Date.now() - cache.lastFetched < 5 * 60 * 1000;
40 + if (!isValid) return null;
41 +
42 + return cache;
43 + },
44 +
45 + // Clear cache
46 + clear: () => {
47 + set({
48 + objetoGasto: {
49 + allItems: null,
50 + grupos: null,
51 + entities: null,
52 + availableYears: null,
53 + lastFetched: null
54 + }
55 + });
56 + }
57 + };
58 +};
59 +
60 +export const clasificadorCache = createClasificadorCache();
This diff is collapsed. Click to expand it.
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
3 import { tweened } from 'svelte/motion'; 3 import { tweened } from 'svelte/motion';
4 import { cubicOut } from 'svelte/easing'; 4 import { cubicOut } from 'svelte/easing';
5 import { supabase } from '$lib/supabase'; 5 import { supabase } from '$lib/supabase';
6 + import Spinner from '$lib/components/ui/Spinner.svelte';
6 7
7 // ══════════════════════════════════════════════════════════════ 8 // ══════════════════════════════════════════════════════════════
8 // ESTADO GENERAL 9 // ESTADO GENERAL
...@@ -886,7 +887,7 @@ ...@@ -886,7 +887,7 @@
886 </div> 887 </div>
887 {:else if loadingComparacion} 888 {:else if loadingComparacion}
888 <div class="comparador-placeholder"> 889 <div class="comparador-placeholder">
889 - <p>Cargando datos...</p> 890 + <Spinner size={48} color="var(--theme-texto, #5A5650)" />
890 </div> 891 </div>
891 {:else if añosComparacion.length === 0} 892 {:else if añosComparacion.length === 0}
892 <div class="comparador-placeholder"> 893 <div class="comparador-placeholder">
......