changed font style, added journey summary, changed card ui
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
<script>
|
||||
import PhotoGallery from '../shared/PhotoGallery.svelte';
|
||||
|
||||
/** @type {{ entry: import('../stores/journalStore.js').JournalEntry, onClick: () => void }} */
|
||||
let { entry, onClick } = $props();
|
||||
|
||||
@@ -9,140 +7,210 @@
|
||||
year: 'numeric', month: 'short', day: 'numeric',
|
||||
});
|
||||
}
|
||||
|
||||
let mainPhoto = $derived(entry.photos[0] ?? null);
|
||||
let thumbPhotos = $derived(entry.photos.slice(1, 4));
|
||||
let extraCount = $derived(entry.photos.length > 4 ? entry.photos.length - 4 : 0);
|
||||
</script>
|
||||
|
||||
<li class="v-item">
|
||||
<div class="v-dot" aria-hidden="true"></div>
|
||||
<div class="v-entry-wrap">
|
||||
<div class="above-card">
|
||||
<time class="above-date" datetime={entry.date}>{formatDate(entry.date)}</time>
|
||||
<span class="above-sep">·</span>
|
||||
<span class="above-loc">{entry.location.city}, {entry.location.country}</span>
|
||||
<span class="above-sep">·</span>
|
||||
<span class="above-days">{entry.days} {entry.days === 1 ? 'day' : 'days'}</span>
|
||||
</div>
|
||||
|
||||
<div class="entry-card" role="button" tabindex="0"
|
||||
onclick={onClick}
|
||||
onkeydown={(e) => e.key === 'Enter' && onClick()}>
|
||||
<div class="entry-card" role="button" tabindex="0"
|
||||
onclick={onClick}
|
||||
onkeydown={(e) => e.key === 'Enter' && onClick()}>
|
||||
|
||||
<PhotoGallery photos={entry.photos} height="220px" />
|
||||
|
||||
<div class="entry-body">
|
||||
<h2 class="entry-title">{entry.title}</h2>
|
||||
{#if entry.memo}
|
||||
<p class="entry-memo">{entry.memo}</p>
|
||||
<!-- Photo grid -->
|
||||
<div class="photo-grid" class:has-thumbs={thumbPhotos.length > 0}>
|
||||
<div class="photo-main">
|
||||
{#if mainPhoto}
|
||||
<img src={mainPhoto} alt="photo 1" loading="lazy" />
|
||||
{:else}
|
||||
<div class="photo-placeholder"></div>
|
||||
{/if}
|
||||
<div class="entry-song">
|
||||
<svg class="song-icon" width="13" height="13" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M9 18V5l12-2v13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="6" cy="18" r="3" stroke="currentColor" stroke-width="2"/>
|
||||
<circle cx="18" cy="16" r="3" stroke="currentColor" stroke-width="2"/>
|
||||
</svg>
|
||||
<span class="song-title">{entry.song.title}</span>
|
||||
<span class="song-sep">·</span>
|
||||
<span class="song-artist">{entry.song.artist}</span>
|
||||
<span class="trip-badge trip-badge--{entry.tripType}">
|
||||
{entry.tripType === 'solo' ? 'Solo' : 'With Friends'}
|
||||
</span>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="overlay">
|
||||
<div class="overlay-top">
|
||||
<span class="trip-badge trip-badge--{entry.tripType}">
|
||||
{entry.tripType === 'solo' ? 'Solo' : 'With Friends'}
|
||||
</span>
|
||||
</div>
|
||||
<div class="overlay-bottom">
|
||||
<span class="city">{entry.location.city}</span>
|
||||
<span class="country">{entry.location.country}</span>
|
||||
<span class="meta">{formatDate(entry.date)} · {entry.days} {entry.days === 1 ? 'day' : 'days'}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if thumbPhotos.length > 0}
|
||||
<div class="photo-thumbs">
|
||||
{#each thumbPhotos as photo, i}
|
||||
<div class="photo-thumb">
|
||||
<img src={photo} alt="photo {i + 2}" loading="lazy" />
|
||||
{#if i === 2 && extraCount > 0}
|
||||
<div class="extra-overlay">+{extraCount}</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<style>
|
||||
/* Above-card meta */
|
||||
.above-card {
|
||||
.v-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 8px;
|
||||
gap: 16px;
|
||||
align-items: flex-start;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.above-date { font-size: 12px; font-weight: 500; color: var(--text-h, #08060d); }
|
||||
.above-loc, .above-days { font-size: 12px; color: var(--text, #6b6375); }
|
||||
.above-sep { font-size: 11px; color: var(--border, #c8c6cc); user-select: none; }
|
||||
|
||||
/* Card */
|
||||
.entry-card {
|
||||
display: block;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid var(--border, #e5e4e7);
|
||||
border-radius: 14px;
|
||||
overflow: hidden;
|
||||
background: var(--bg, #fff);
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.2s, transform 0.15s;
|
||||
text-align: left;
|
||||
}
|
||||
.entry-card:hover {
|
||||
box-shadow: 0 6px 24px rgba(0,0,0,0.1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.entry-body { padding: 14px 18px 18px; }
|
||||
|
||||
.entry-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--text-h, #08060d);
|
||||
margin: 0 0 6px;
|
||||
letter-spacing: -0.2px;
|
||||
}
|
||||
|
||||
.entry-memo {
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: var(--text, #6b6375);
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
.entry-song {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
font-size: 12px;
|
||||
color: var(--text, #6b6375);
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid var(--border, #e5e4e7);
|
||||
}
|
||||
.song-icon { flex-shrink: 0; color: var(--accent, #aa3bff); }
|
||||
.song-title { font-weight: 500; color: var(--text-h, #08060d); }
|
||||
.song-sep { opacity: 0.35; }
|
||||
|
||||
.entry-song .trip-badge { margin-left: auto; flex-shrink: 0; }
|
||||
.trip-badge {
|
||||
display: inline-block;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
padding: 2px 8px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
.trip-badge--solo { background: rgba(245,158,11,0.12); color: #b45309; }
|
||||
.trip-badge--friends { background: rgba(59,130,246,0.12); color: #1d4ed8; }
|
||||
|
||||
/* Timeline line & dot */
|
||||
.v-item { display: flex; gap: 24px; align-items: flex-start; padding-bottom: 36px; }
|
||||
.v-item:last-child { padding-bottom: 0; }
|
||||
|
||||
.v-dot {
|
||||
flex-shrink: 0;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent, #aa3bff);
|
||||
border: 3px solid var(--bg, #fff);
|
||||
box-shadow: 0 0 0 2px var(--accent, #aa3bff);
|
||||
margin-top: 28px;
|
||||
background: var(--accent);
|
||||
margin-top: 22px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.v-entry-wrap { flex: 1; display: flex; flex-direction: column; }
|
||||
/* Card */
|
||||
.entry-card {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.2s, transform 0.15s;
|
||||
box-shadow: 0 2px 12px rgba(99,102,241,0.08);
|
||||
}
|
||||
.entry-card:hover {
|
||||
box-shadow: var(--shadow);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.v-dot { width: 18px; height: 18px; }
|
||||
.v-item { gap: 16px; }
|
||||
/* Photo grid */
|
||||
.photo-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
height: 220px;
|
||||
background: #111;
|
||||
}
|
||||
.photo-grid.has-thumbs {
|
||||
grid-template-columns: 2fr 1fr;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
/* Main photo + overlay */
|
||||
.photo-main {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
.photo-main img,
|
||||
.photo-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
.photo-placeholder { background: var(--accent-bg); }
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 14px;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
rgba(0,0,0,0.28) 0%,
|
||||
transparent 35%,
|
||||
transparent 50%,
|
||||
rgba(0,0,0,0.65) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.overlay-top {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.overlay-bottom {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.city {
|
||||
font-size: 12px;
|
||||
font-weight: 300;
|
||||
color: rgba(255,255,255,0.75);
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.country {
|
||||
font-size: 22px;
|
||||
font-weight: 400;
|
||||
color: #fff;
|
||||
letter-spacing: -0.5px;
|
||||
line-height: 1.1;
|
||||
text-shadow: 0 1px 8px rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.meta {
|
||||
font-size: 12px;
|
||||
font-weight: 300;
|
||||
color: rgba(255,255,255,0.7);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Badges */
|
||||
.trip-badge {
|
||||
font-size: 11px;
|
||||
font-weight: 400;
|
||||
padding: 3px 10px;
|
||||
border-radius: 20px;
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
.trip-badge--solo { background: rgba(245,158,11,0.75); color: #fff; }
|
||||
.trip-badge--friends { background: rgba(99,102,241,0.75); color: #fff; }
|
||||
|
||||
/* Thumbs */
|
||||
.photo-thumbs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
.photo-thumb {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
min-height: 0;
|
||||
}
|
||||
.photo-thumb img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.extra-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(0,0,0,0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user