diff --git a/config/site.json b/config/site.json index ea9722c..dcb307a 100644 --- a/config/site.json +++ b/config/site.json @@ -57,6 +57,52 @@ "description": "Enter your gallery code to view and download your photos", "placeholder": "Enter your gallery code" }, + "locations": [ + { + "id": "river-bottoms", + "name": "River Bottoms", + "description": "A stunning riverside setting with golden light filtering through the trees — perfect for that warm, natural feel.", + "tags": ["Outdoor", "Golden hour", "Nature"], + "heroImage": "/images/locations/river-bottoms/hero.jpg", + "galleryImages": [ + "/images/locations/river-bottoms/1.jpg", + "/images/locations/river-bottoms/2.jpg" + ] + }, + { + "id": "city-park", + "name": "City Park", + "description": "Lush green spaces with open fields, mature trees, and beautiful walking paths — great for families and couples.", + "tags": ["Outdoor", "Green space", "Versatile"], + "heroImage": "/images/locations/city-park/hero.jpg", + "galleryImages": [ + "/images/locations/city-park/1.jpg", + "/images/locations/city-park/2.jpg" + ] + }, + { + "id": "downtown", + "name": "Downtown", + "description": "Urban backdrops with brick walls, murals, and architectural details — ideal for seniors and creative portraits.", + "tags": ["Urban", "Architecture", "Creative"], + "heroImage": "/images/locations/downtown/hero.jpg", + "galleryImages": [ + "/images/locations/downtown/1.jpg", + "/images/locations/downtown/2.jpg" + ] + }, + { + "id": "studio", + "name": "Studio", + "description": "A clean, controlled environment with professional lighting — great for newborns, headshots, and consistent results.", + "tags": ["Indoor", "Controlled lighting", "Year-round"], + "heroImage": "/images/locations/studio/hero.jpg", + "galleryImages": [ + "/images/locations/studio/1.jpg", + "/images/locations/studio/2.jpg" + ] + } + ], "booking": { "venmoUsername": "LisiLouPhoto", "sessionTypes": [ diff --git a/public/images/locations/city-park/.gitkeep b/public/images/locations/city-park/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/images/locations/downtown/.gitkeep b/public/images/locations/downtown/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/images/locations/river-bottoms/.gitkeep b/public/images/locations/river-bottoms/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/images/locations/studio/.gitkeep b/public/images/locations/studio/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/index.html b/src/index.html index 6392ade..0d030c8 100644 --- a/src/index.html +++ b/src/index.html @@ -846,6 +846,160 @@ display: none; } + /* Location cards */ + .location-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + gap: 1rem; + } + + .location-card { + border: 1px solid var(--color-accent); + background: var(--color-white); + cursor: pointer; + position: relative; + transition: border-color 0.3s var(--transition-smooth); + user-select: none; + } + + .location-card:hover { border-color: var(--color-primary); } + .location-card.selected { border-color: var(--color-primary); } + + .location-card-image { + position: relative; + aspect-ratio: 4/3; + overflow: hidden; + background: var(--color-bg-warm); + } + + .location-card-image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.5s var(--transition-smooth); + display: block; + } + + .location-card:hover .location-card-image img { transform: scale(1.06); } + + .location-img-placeholder { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, var(--color-bg-warm), var(--color-accent)); + font-family: var(--font-display); + font-size: 0.85rem; + font-style: italic; + color: var(--color-text-light); + padding: 0.5rem; + text-align: center; + } + + .location-card-check { + position: absolute; + top: 0.6rem; + right: 0.6rem; + width: 26px; + height: 26px; + border-radius: 50%; + background: var(--color-primary); + color: var(--color-white); + display: none; + align-items: center; + justify-content: center; + font-size: 0.75rem; + z-index: 1; + box-shadow: 0 2px 6px rgba(0,0,0,0.2); + } + + .location-card.selected .location-card-check { display: flex; } + + .location-card-body { padding: 0.75rem 0.9rem 0.9rem; } + + .location-card-name { + font-family: var(--font-display); + font-size: 1.05rem; + font-weight: 400; + color: var(--color-text); + margin-bottom: 0.4rem; + } + + .location-tags { display: flex; flex-wrap: wrap; gap: 0.3rem; } + + .location-tag { + font-size: 0.58rem; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--color-primary); + border: 1px solid var(--color-accent); + padding: 0.15rem 0.45rem; + } + + /* Detail expand panel */ + .location-detail { + overflow: hidden; + max-height: 0; + opacity: 0; + transition: max-height 0.4s var(--transition-smooth), opacity 0.3s, margin-top 0.3s; + margin-top: 0; + } + + .location-detail.open { + max-height: 500px; + opacity: 1; + margin-top: 1.25rem; + } + + .location-detail-inner { + border: 1px solid var(--color-accent); + padding: 1.25rem; + background: var(--color-bg-warm); + } + + .location-gallery { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); + gap: 0.5rem; + margin-bottom: 1rem; + } + + .location-gallery-item { + aspect-ratio: 4/3; + overflow: hidden; + background: var(--color-accent); + } + + .location-gallery-item img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + transition: transform 0.4s var(--transition-smooth); + } + + .location-gallery-item img:hover { transform: scale(1.05); } + + .location-detail-name { + font-family: var(--font-display); + font-size: 1.2rem; + font-weight: 300; + color: var(--color-text); + margin-bottom: 0.5rem; + } + + .location-detail-desc { + font-size: 0.85rem; + color: var(--color-text); + line-height: 1.65; + margin-bottom: 0.75rem; + } + + @media (max-width: 768px) { + .location-grid { grid-template-columns: 1fr 1fr; } + } + /* Contract step */ .contract-placeholder { background: var(--color-bg-warm); @@ -1155,29 +1309,19 @@
- +

Pick a Location

Choose where you'd like your session to take place.

-
-
-
Outdoor Park
-
Natural setting
-
-
-
Studio
-
Controlled lighting
-
-
-
Urban
-
City backdrop
-
-
-
Your Choice
-
Suggest a location
+
+
+
+ +
+

+
-
@@ -1549,6 +1693,67 @@
`; } + function renderLocationCards() { + const locations = window.siteConfig?.locations; + const grid = document.getElementById('location-options'); + + if (!locations || locations.length === 0) { + grid.innerHTML = '

No locations configured yet.

'; + return; + } + + grid.innerHTML = locations.map(loc => { + const imgHtml = loc.heroImage + ? `${loc.name}` + : `
${loc.name}
`; + const tags = (loc.tags || []).map(t => `${t}`).join(''); + return ` +
+
+ ${imgHtml} +
+
+
+
${loc.name}
+
${tags}
+
+
`; + }).join(''); + } + + function selectLocation(id) { + const locations = window.siteConfig?.locations || []; + const loc = locations.find(l => l.id === id); + if (!loc) return; + + document.querySelectorAll('.location-card').forEach(c => c.classList.remove('selected')); + const card = document.querySelector(`.location-card[data-id="${id}"]`); + if (card) card.classList.add('selected'); + bookingState.sessionLocation = id; + + const detail = document.getElementById('location-detail'); + const wasOpen = detail.classList.contains('open') && detail.dataset.locationId === id; + + if (wasOpen) { + detail.classList.remove('open'); + detail.dataset.locationId = ''; + } else { + const gallery = (loc.galleryImages || []); + document.getElementById('location-detail-gallery').innerHTML = gallery.length + ? gallery.map(src => ` + `).join('') + : ''; + document.getElementById('location-detail-name').textContent = loc.name; + document.getElementById('location-detail-desc').textContent = loc.description || ''; + document.getElementById('location-detail-tags').innerHTML = (loc.tags || []) + .map(t => `${t}`).join(''); + detail.dataset.locationId = id; + detail.classList.add('open'); + } + } + function openBooking() { document.getElementById('booking-overlay').classList.add('active'); document.body.style.overflow = 'hidden'; @@ -1564,6 +1769,10 @@ document.getElementById('session-date').value = ''; renderSessionTypeCards(); renderSessionLengthCards(); + renderLocationCards(); + const locationDetail = document.getElementById('location-detail'); + locationDetail.classList.remove('open'); + locationDetail.dataset.locationId = ''; goToStep(1); } @@ -1639,7 +1848,8 @@ document.getElementById('summary-date').textContent = bookingState.sessionDate || '—'; document.getElementById('summary-type').textContent = displayType; document.getElementById('summary-length').textContent = lengthLabels[bookingState.sessionLength] || '—'; - document.getElementById('summary-location').textContent = bookingState.sessionLocation || '—'; + const loc = (window.siteConfig?.locations || []).find(l => l.id === bookingState.sessionLocation); + document.getElementById('summary-location').textContent = loc?.name || bookingState.sessionLocation || '—'; } function validateStep(step) { @@ -1720,7 +1930,8 @@ ? 'other: ' + bookingState.sessionTypeOther : bookingState.sessionType, session_length: bookingState.sessionLength, - location: bookingState.sessionLocation, + location: (window.siteConfig?.locations || []).find(l => l.id === bookingState.sessionLocation)?.name + || bookingState.sessionLocation, }), }); if (!res.ok) throw new Error('server error');