Migrated components to Svelte 5 runes and fixed tooltip
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
import StationRow from './StationRow.svelte';
|
import StationRow from './StationRow.svelte';
|
||||||
import groups from '$lib/groups.json';
|
import groups from '$lib/groups.json';
|
||||||
|
|
||||||
export let stations = [];
|
let { stations = [] } = $props();
|
||||||
|
|
||||||
// Set per lookup O(1): con molte centraline, includes() su array per ogni riga sarebbe O(n²).
|
// Set per lookup O(1): con molte centraline, includes() su array per ogni riga sarebbe O(n²).
|
||||||
const groupedIds = new Set(groups.flatMap(g => g.ids));
|
const groupedIds = new Set(groups.flatMap(g => g.ids));
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const sections = [
|
const sections = $derived([
|
||||||
...groups.map(g => ({
|
...groups.map(g => ({
|
||||||
name: g.name,
|
name: g.name,
|
||||||
stations: sortStations(stations.filter(s => g.ids.includes(s.pk))),
|
stations: sortStations(stations.filter(s => g.ids.includes(s.pk))),
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
name: 'Altre',
|
name: 'Altre',
|
||||||
stations: sortStations(stations.filter(s => !groupedIds.has(s.pk))),
|
stations: sortStations(stations.filter(s => !groupedIds.has(s.pk))),
|
||||||
},
|
},
|
||||||
].filter(s => s.stations.length > 0);
|
].filter(s => s.stations.length > 0));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
|||||||
@@ -5,9 +5,7 @@
|
|||||||
import { downloadCsv, buildFilename } from '$lib/csv.js';
|
import { downloadCsv, buildFilename } from '$lib/csv.js';
|
||||||
import { enqueue } from '$lib/download-pool.js';
|
import { enqueue } from '$lib/download-pool.js';
|
||||||
|
|
||||||
export let station;
|
let { station } = $props();
|
||||||
|
|
||||||
const isActive = station.ended_at === null;
|
|
||||||
|
|
||||||
const formatDate = d => new Intl.DateTimeFormat('it-IT', {
|
const formatDate = d => new Intl.DateTimeFormat('it-IT', {
|
||||||
timeZone: 'Europe/Rome',
|
timeZone: 'Europe/Rome',
|
||||||
@@ -16,18 +14,18 @@
|
|||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
}).format(new Date(d));
|
}).format(new Date(d));
|
||||||
|
|
||||||
const createdDate = formatDate(station.created_at);
|
const isActive = $derived(station.ended_at === null);
|
||||||
const endDate = isActive ? null : formatDate(station.ended_at);
|
const createdDate = $derived(formatDate(station.created_at));
|
||||||
|
const endDate = $derived(isActive ? null : formatDate(station.ended_at));
|
||||||
|
|
||||||
let showTooltip = false;
|
let downloading = $state(false);
|
||||||
let downloading = false;
|
let cancelling = $state(false);
|
||||||
let cancelling = false;
|
let completed = $state(false);
|
||||||
let completed = false;
|
|
||||||
let controller = null;
|
let controller = null;
|
||||||
let currentDay = 0;
|
let currentDay = $state(0);
|
||||||
let totalDays = 0;
|
let totalDays = $state(0);
|
||||||
|
|
||||||
$: pct = totalDays > 0 ? (currentDay / totalDays) * 100 : 0;
|
let pct = $derived(totalDays > 0 ? (currentDay / totalDays) * 100 : 0);
|
||||||
|
|
||||||
async function startDownload() {
|
async function startDownload() {
|
||||||
const { buildCsvAsync } = await import('$lib/csv-pool.js');
|
const { buildCsvAsync } = await import('$lib/csv-pool.js');
|
||||||
@@ -94,15 +92,9 @@
|
|||||||
<div class="right">
|
<div class="right">
|
||||||
<span class="date">Attivata il {createdDate}</span>
|
<span class="date">Attivata il {createdDate}</span>
|
||||||
<span class="sep">·</span>
|
<span class="sep">·</span>
|
||||||
<span
|
<span class="status" class:active={isActive} class:ended={!isActive}>
|
||||||
class="status"
|
|
||||||
class:active={isActive}
|
|
||||||
class:ended={!isActive}
|
|
||||||
on:mouseenter={() => showTooltip = true}
|
|
||||||
on:mouseleave={() => showTooltip = false}
|
|
||||||
>
|
|
||||||
{isActive ? 'Attiva' : 'Terminata'}
|
{isActive ? 'Attiva' : 'Terminata'}
|
||||||
{#if !isActive && showTooltip}
|
{#if !isActive}
|
||||||
<span class="tooltip">Terminata il {endDate}</span>
|
<span class="tooltip">Terminata il {endDate}</span>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
@@ -110,7 +102,7 @@
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
title={downloading ? 'Annulla' : 'Scarica CSV'}
|
title={downloading ? 'Annulla' : 'Scarica CSV'}
|
||||||
on:click={downloading ? cancel : startDownload}
|
onclick={downloading ? cancel : startDownload}
|
||||||
class:downloading
|
class:downloading
|
||||||
class:completed
|
class:completed
|
||||||
>
|
>
|
||||||
@@ -147,7 +139,6 @@
|
|||||||
<style>
|
<style>
|
||||||
.card {
|
.card {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
@@ -277,7 +268,8 @@
|
|||||||
.tooltip {
|
.tooltip {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: calc(100% + 16px);
|
bottom: calc(100% + 16px);
|
||||||
right: 0;
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
@@ -288,13 +280,20 @@
|
|||||||
padding: 0.45em 0.9em;
|
padding: 0.45em 0.9em;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status:hover .tooltip {
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip::after {
|
.tooltip::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 100%;
|
top: 100%;
|
||||||
right: 1rem;
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
border: 6px solid transparent;
|
border: 6px solid transparent;
|
||||||
border-top-color: var(--border);
|
border-top-color: var(--border);
|
||||||
}
|
}
|
||||||
@@ -306,6 +305,8 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
height: 3px;
|
height: 3px;
|
||||||
background: var(--border);
|
background: var(--border);
|
||||||
|
border-radius: 0 0 14px 14px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bar {
|
.bar {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import StationList from '$lib/components/StationList.svelte';
|
import StationList from '$lib/components/StationList.svelte';
|
||||||
|
|
||||||
export let data;
|
let { data } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="page">
|
<div class="page">
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ import adapter from '@sveltejs/adapter-auto';
|
|||||||
|
|
||||||
/** @type {import('@sveltejs/kit').Config} */
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
const config = {
|
const config = {
|
||||||
|
compilerOptions: {
|
||||||
|
runes: true,
|
||||||
|
},
|
||||||
kit: {
|
kit: {
|
||||||
adapter: adapter()
|
adapter: adapter()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user