fix: UI world map
This commit is contained in:
@@ -7,18 +7,23 @@
|
||||
|
||||
let fileInput;
|
||||
let uploading = $state(false);
|
||||
let uploadError = $state('');
|
||||
|
||||
function remove(index) {
|
||||
onchange(photos.filter((_, i) => i !== index));
|
||||
uploadError = '';
|
||||
}
|
||||
|
||||
async function addFiles(e) {
|
||||
const files = Array.from(e.currentTarget.files ?? []);
|
||||
if (!files.length) return;
|
||||
uploading = true;
|
||||
uploadError = '';
|
||||
try {
|
||||
const urls = await Promise.all(files.map(uploadPhoto));
|
||||
onchange([...photos, ...urls]);
|
||||
} catch (err) {
|
||||
uploadError = err?.message ?? 'Upload failed. Check Firebase Storage rules.';
|
||||
} finally {
|
||||
uploading = false;
|
||||
e.currentTarget.value = '';
|
||||
@@ -68,6 +73,10 @@
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if uploadError}
|
||||
<div class="upload-error">{uploadError}</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -183,4 +192,15 @@
|
||||
transition: border-color 0.15s, color 0.15s;
|
||||
}
|
||||
.add-cell:hover { border-color: var(--accent-border); color: var(--accent); }
|
||||
|
||||
.upload-error {
|
||||
font-size: 12px;
|
||||
color: #ef4444;
|
||||
background: #fef2f2;
|
||||
border: 1px solid #fecaca;
|
||||
border-radius: 6px;
|
||||
padding: 8px 10px;
|
||||
line-height: 1.4;
|
||||
word-break: break-word;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import worldData from 'world-atlas/countries-50m.json';
|
||||
import { get } from 'svelte/store';
|
||||
import { journals } from '../stores/journalStore.js';
|
||||
import airplaneImg from '../../assets/airplane.png';
|
||||
import airplaneImg from '../../assets/airplane-animation.png';
|
||||
|
||||
let { onclose, onprogress, mode = 'map', onmodechange } = $props();
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { getSelected, setTotalCount, getFlashing } from '../layout/selection.svelte.js';
|
||||
import { getUserProfile } from '../auth/userStore.svelte.js';
|
||||
import { nameToId } from '../shared/countries.js';
|
||||
import homeIconUrl from '../../assets/home.png';
|
||||
import crayonCursorUrl from '../../assets/logo-cursor.png';
|
||||
|
||||
let { onCountryClick = (_name) => {} } = $props();
|
||||
@@ -103,6 +104,28 @@
|
||||
|
||||
$effect(updateAllFills);
|
||||
|
||||
function placeHomeMarker() {
|
||||
if (!_g || !_pathFn || !_countries) return;
|
||||
_g.selectAll('.home-marker').remove();
|
||||
const name = getUserProfile()?.homeCountry;
|
||||
if (!name) return;
|
||||
const found = _countries.find(f => f.properties.name === name);
|
||||
if (!found) return;
|
||||
const [cx, cy] = _pathFn.centroid(found);
|
||||
if (isNaN(cx) || isNaN(cy)) return;
|
||||
const SIZE = 14;
|
||||
_g.append('image')
|
||||
.attr('class', 'home-marker')
|
||||
.attr('href', homeIconUrl)
|
||||
.attr('x', cx - SIZE / 2)
|
||||
.attr('y', cy - SIZE / 2)
|
||||
.attr('width', SIZE)
|
||||
.attr('height', SIZE)
|
||||
.style('pointer-events', 'none');
|
||||
}
|
||||
|
||||
$effect(placeHomeMarker);
|
||||
|
||||
$effect(() => {
|
||||
const flashSet = getFlashing();
|
||||
const paths = _paths; // reactive read so effect re-runs when _paths is set
|
||||
@@ -166,7 +189,7 @@
|
||||
})
|
||||
.on('mousemove', (event) => {
|
||||
const [x, y] = d3.pointer(event, frameEl);
|
||||
tooltip.style('left', (x + 10) + 'px').style('top', (y - 28) + 'px');
|
||||
tooltip.style('left', (x + 22) + 'px').style('top', (y - 28) + 'px');
|
||||
})
|
||||
.on('mouseleave', (event, d) => {
|
||||
const s = getSelected();
|
||||
@@ -207,6 +230,7 @@
|
||||
}
|
||||
|
||||
renderMicrostates();
|
||||
placeHomeMarker();
|
||||
|
||||
const zoom = d3.zoom()
|
||||
.scaleExtent([1, 32])
|
||||
@@ -230,8 +254,9 @@
|
||||
fitProjection(projection, width, height);
|
||||
const countryPaths = _g.selectAll('path');
|
||||
countryPaths.attr('d', path);
|
||||
updateFill(countryPaths);
|
||||
updateAllFills();
|
||||
renderMicrostates();
|
||||
placeHomeMarker();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user