2941b14b38
- Moved contents of main_dc/yalarba/easySite/easySite/ up to easySite/ - Updated docker-compose.yml build context path - Deleted empty nested easySite/ directory
803 lines
20 KiB
Vue
803 lines
20 KiB
Vue
<template>
|
||
<div class="page-wrapper">
|
||
|
||
<main class="object-page">
|
||
<div class="container max-w-6xl">
|
||
<nav class="breadcrumbs">
|
||
<NuxtLink to="/objects" class="breadcrumb-link">Все объекты</NuxtLink>
|
||
<span class="breadcrumb-separator">/</span>
|
||
<span class="breadcrumb-current">{{ object?.title || object?.short_name }}</span>
|
||
</nav>
|
||
|
||
<div v-if="loading" class="loading-state">
|
||
<div class="loading-spinner"/>
|
||
<p class="loading-text">Загрузка объекта...</p>
|
||
</div>
|
||
|
||
<div v-else-if="!object" class="empty-state">
|
||
<div class="empty-icon">🏢</div>
|
||
<h3 class="empty-title">Объект не найден</h3>
|
||
<p class="empty-description">Возможно, объект был удалён или у вас нет к нему доступа</p>
|
||
<NuxtLink to="/objects" class="btn btn-primary">Вернуться к списку</NuxtLink>
|
||
</div>
|
||
|
||
<template v-else>
|
||
<div class="page-header">
|
||
<div class="header-content">
|
||
<div class="header-text">
|
||
<div class="object-meta">
|
||
<span class="object-type">{{ getTypeLabel(object.type) }}</span>
|
||
<div class="rating">
|
||
<div class="rating-stars">
|
||
<span
|
||
v-for="star in 5"
|
||
:key="star"
|
||
class="rating-star"
|
||
:class="{ empty: star > Math.round(touristScore) }">
|
||
★
|
||
</span>
|
||
</div>
|
||
<span class="rating-value">{{ touristScore }}</span>
|
||
<span class="reviews-count">({{ object.feedback_count }} отзывов)</span>
|
||
</div>
|
||
</div>
|
||
<h1 class="page-title">{{ object.title || object.short_name }}</h1>
|
||
<div class="object-location">
|
||
<span class="location-icon">📍</span>
|
||
{{ object.address }}
|
||
</div>
|
||
</div>
|
||
<div class="header-actions">
|
||
<div class="price-section">
|
||
<div class="price">{{ formatPrice(object.price) }}</div>
|
||
<div class="price-period">{{ pricePeriodLabel }}</div>
|
||
</div>
|
||
<div class="action-buttons">
|
||
<button class="btn btn-primary btn-large" @click="showBookingModal = true">
|
||
Забронировать
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="gallery-section">
|
||
<div class="main-image">
|
||
<img :src="mainImage" :alt="object.title || object.short_name" class="gallery-image" @click="openGallery(0)">
|
||
</div>
|
||
<div v-if="object.images && object.images.length > 1" class="thumbnails">
|
||
<div
|
||
v-for="(image, index) in object.images.slice(1, 5)"
|
||
:key="image.id"
|
||
class="thumbnail"
|
||
@click="openGallery(index + 1)">
|
||
<img :src="image.url" :alt="`${object.title} - фото ${index + 2}`">
|
||
<div v-if="index === 3 && object.images.length > 5" class="more-images">
|
||
+{{ object.images.length - 5 }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="content-grid">
|
||
<div class="content-main">
|
||
<section class="content-section">
|
||
<h2 class="section-title">Описание</h2>
|
||
<p class="object-description">{{ object.description || object.short_description }}</p>
|
||
</section>
|
||
|
||
<section v-if="object.amenities && object.amenities.length" class="content-section">
|
||
<h2 class="section-title">Удобства</h2>
|
||
<div class="amenities-grid">
|
||
<div v-for="amenity in object.amenities" :key="amenity.id" class="amenity-item">
|
||
<span class="amenity-icon">{{ amenity.icon || '✅' }}</span>
|
||
<span class="amenity-text">{{ amenity.name }}</span>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="content-section">
|
||
<h2 class="section-title">Контакты</h2>
|
||
<div class="contact-info">
|
||
<div v-if="object.phone" class="contact-item">
|
||
<span class="contact-icon">📞</span>
|
||
<a :href="`tel:${object.phone}`" class="contact-link">{{ object.phone }}</a>
|
||
</div>
|
||
<div v-if="object.email" class="contact-item">
|
||
<span class="contact-icon">✉️</span>
|
||
<a :href="`mailto:${object.email}`" class="contact-link">{{ object.email }}</a>
|
||
</div>
|
||
<div v-if="object.site" class="contact-item">
|
||
<span class="contact-icon">🌐</span>
|
||
<a :href="object.site" target="_blank" class="contact-link">{{ object.site }}</a>
|
||
</div>
|
||
<div v-if="object.address" class="contact-item">
|
||
<span class="contact-icon">📍</span>
|
||
<span class="contact-text">{{ object.address }}</span>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<div class="content-sidebar">
|
||
<div class="booking-card card">
|
||
<div class="card-header">
|
||
<h3 class="card-title">Бронирование</h3>
|
||
<div class="price-info">
|
||
<span class="price-large">{{ formatPrice(object.price) }}</span>
|
||
<span class="price-period">{{ pricePeriodLabel }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="booking-form">
|
||
<div class="form-group">
|
||
<label class="form-label">Даты</label>
|
||
<div class="date-inputs">
|
||
<input v-model="bookingDates.checkIn" type="date" class="form-input" placeholder="Заезд">
|
||
<input v-model="bookingDates.checkOut" type="date" class="form-input" placeholder="Выезд">
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label">Гости</label>
|
||
<select v-model="bookingGuests" class="form-select">
|
||
<option value="1">1 гость</option>
|
||
<option value="2">2 гостя</option>
|
||
<option value="3">3 гостя</option>
|
||
<option value="4">4 гостя</option>
|
||
</select>
|
||
</div>
|
||
<button
|
||
class="btn btn-primary btn-large"
|
||
:disabled="!bookingDates.checkIn || !bookingDates.checkOut"
|
||
@click="showBookingModal = true">
|
||
Забронировать
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="contact-card card">
|
||
<div class="card-header">
|
||
<h3 class="card-title">Контактная информация</h3>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="contact-actions">
|
||
<a v-if="object.phone" :href="`tel:${object.phone}`" class="btn btn-outline btn-with-icon">
|
||
<span>📞</span>
|
||
Позвонить
|
||
</a>
|
||
<a v-if="object.email" :href="`mailto:${object.email}`" class="btn btn-outline btn-with-icon">
|
||
<span>✉️</span>
|
||
Написать
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div v-if="isOwner" class="owner-actions card">
|
||
<div class="card-header">
|
||
<h3 class="card-title">Управление объектом</h3>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="action-buttons">
|
||
<NuxtLink :to="`/objects/${object.id}/edit`" class="btn btn-outline btn-with-icon">
|
||
<span>✏️</span>
|
||
Редактировать
|
||
</NuxtLink>
|
||
<button
|
||
class="btn btn-outline btn-with-icon"
|
||
:class="{ 'btn-primary': !object.is_active }"
|
||
@click="toggleObjectStatus">
|
||
<span>{{ object.is_active ? '⏸️' : '▶️' }}</span>
|
||
{{ object.is_active ? 'Деактивировать' : 'Активировать' }}
|
||
</button>
|
||
<button
|
||
class="btn btn-outline btn-with-icon delete-btn"
|
||
@click="deleteObject">
|
||
<span>🗑️</span>
|
||
Удалить
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</div>
|
||
</main>
|
||
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import type { ObjectResponse } from '~/types/objects'
|
||
|
||
const route = useRoute()
|
||
const { getById, remove } = useObjects()
|
||
const { user } = useAuth()
|
||
|
||
const object = ref<ObjectResponse | null>(null)
|
||
const loading = ref(true)
|
||
const showBookingModal = ref(false)
|
||
const showGallery = ref(false)
|
||
const galleryIndex = ref(0)
|
||
|
||
const bookingDates = ref({ checkIn: '', checkOut: '' })
|
||
const bookingGuests = ref('2')
|
||
|
||
const touristScore = computed(() => {
|
||
return object.value?.feedback_count || 0
|
||
})
|
||
|
||
const mainImage = computed(() => {
|
||
if (object.value?.images?.length) {
|
||
return object.value.images[0].url
|
||
}
|
||
return '/images/placeholder.jpg'
|
||
})
|
||
|
||
const pricePeriodLabel = computed(() => {
|
||
const labels: Record<string, string> = {
|
||
per_night: 'за ночь',
|
||
per_person: 'за человека',
|
||
per_tour: 'за тур',
|
||
per_hour: 'за час'
|
||
}
|
||
const p = object.value?.price_period
|
||
return p ? labels[p] || p : ''
|
||
})
|
||
|
||
const isOwner = computed(() => {
|
||
if (!user.value || !object.value) return false
|
||
return user.value.id === object.value.owner_id
|
||
})
|
||
|
||
onMounted(async () => {
|
||
loading.value = true
|
||
try {
|
||
const id = parseInt(route.params.id as string)
|
||
object.value = await getById(id)
|
||
|
||
useSeoMeta({
|
||
title: `${object.value.title || object.value.short_name} - EasySite`,
|
||
description: object.value.description || object.value.short_description,
|
||
ogTitle: object.value.title || object.value.short_name,
|
||
ogDescription: object.value.description || object.value.short_description,
|
||
ogImage: mainImage.value
|
||
})
|
||
} catch (error) {
|
||
console.error('Error loading object:', error)
|
||
object.value = null
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
})
|
||
|
||
const getTypeLabel = (type: string | undefined) => {
|
||
const types: Record<string, string> = {
|
||
hotel: '🏨 Гостиница',
|
||
sanatorium: '🏥 Санаторий',
|
||
guest_house: '🏡 Гостевой дом',
|
||
tour: '🧳 Тур',
|
||
restaurant: '🍴 Ресторан'
|
||
}
|
||
return types[type || ''] || type || ''
|
||
}
|
||
|
||
const formatPrice = (price: number | undefined) => {
|
||
if (!price && price !== 0) return '—'
|
||
return new Intl.NumberFormat('ru-RU', {
|
||
style: 'currency',
|
||
currency: 'RUB',
|
||
minimumFractionDigits: 0
|
||
}).format(price)
|
||
}
|
||
|
||
const openGallery = (index: number) => {
|
||
galleryIndex.value = index
|
||
showGallery.value = true
|
||
}
|
||
|
||
const toggleObjectStatus = async () => {
|
||
if (!object.value) return
|
||
// TODO: Implement status toggle via update API
|
||
object.value.is_active = !object.value.is_active
|
||
}
|
||
|
||
const deleteObject = async () => {
|
||
if (!object.value) return
|
||
if (!confirm('Вы уверены, что хотите удалить этот объект?')) return
|
||
try {
|
||
await remove(object.value.id)
|
||
await navigateTo('/objects/my-objects')
|
||
} catch (error) {
|
||
console.error('Error deleting object:', error)
|
||
alert('Ошибка при удалении объекта')
|
||
}
|
||
}
|
||
|
||
const handleBooking = () => {
|
||
showBookingModal.value = false
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.object-page {
|
||
padding: var(--space-xl) 0;
|
||
min-height: calc(100vh - 160px);
|
||
background: var(--bg-secondary);
|
||
}
|
||
|
||
.breadcrumbs {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-xs);
|
||
margin-bottom: var(--space-lg);
|
||
font-size: var(--text-sm);
|
||
color: var(--text-tertiary);
|
||
}
|
||
|
||
.breadcrumb-link {
|
||
color: var(--primary-500);
|
||
text-decoration: none;
|
||
transition: color 0.3s ease;
|
||
}
|
||
|
||
.breadcrumb-link:hover {
|
||
color: var(--primary-600);
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.breadcrumb-separator {
|
||
color: var(--text-tertiary);
|
||
}
|
||
|
||
.breadcrumb-current {
|
||
color: var(--text-primary);
|
||
font-weight: var(--font-medium);
|
||
}
|
||
|
||
.page-header {
|
||
background: var(--bg-primary);
|
||
border-radius: var(--radius-lg);
|
||
padding: var(--space-xl);
|
||
margin-bottom: var(--space-lg);
|
||
box-shadow: var(--shadow-sm);
|
||
border: 1px solid var(--border-light);
|
||
}
|
||
|
||
.header-content {
|
||
display: grid;
|
||
grid-template-columns: 1fr auto;
|
||
gap: var(--space-xl);
|
||
align-items: flex-start;
|
||
}
|
||
|
||
.header-text {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.object-meta {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-lg);
|
||
margin-bottom: var(--space-sm);
|
||
}
|
||
|
||
.object-type {
|
||
padding: var(--space-xs) var(--space-sm);
|
||
background: var(--primary-100);
|
||
color: var(--primary-700);
|
||
border-radius: var(--radius-sm);
|
||
font-size: var(--text-sm);
|
||
font-weight: var(--font-medium);
|
||
}
|
||
|
||
.rating {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-xs);
|
||
}
|
||
|
||
.rating-stars {
|
||
display: flex;
|
||
gap: 2px;
|
||
}
|
||
|
||
.rating-star {
|
||
color: var(--secondary-400);
|
||
font-size: var(--text-lg);
|
||
}
|
||
|
||
.rating-star.empty {
|
||
color: var(--gray-300);
|
||
}
|
||
|
||
.rating-value {
|
||
font-weight: var(--font-semibold);
|
||
color: var(--text-primary);
|
||
}
|
||
|
||
.reviews-count {
|
||
font-size: var(--text-sm);
|
||
color: var(--text-tertiary);
|
||
}
|
||
|
||
.page-title {
|
||
font-family: var(--font-heading);
|
||
font-size: var(--text-4xl);
|
||
font-weight: var(--font-bold);
|
||
color: var(--text-primary);
|
||
margin: 0;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
.object-location {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-xs);
|
||
font-size: var(--text-lg);
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
.location-icon {
|
||
font-size: var(--text-xl);
|
||
}
|
||
|
||
.header-actions {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-lg);
|
||
min-width: 280px;
|
||
}
|
||
|
||
.price-section {
|
||
text-align: center;
|
||
padding: var(--space-lg);
|
||
background: var(--bg-secondary);
|
||
border-radius: var(--radius-lg);
|
||
border: 1px solid var(--border-light);
|
||
}
|
||
|
||
.price {
|
||
font-family: var(--font-heading);
|
||
font-size: var(--text-3xl);
|
||
font-weight: var(--font-bold);
|
||
color: var(--primary-600);
|
||
line-height: 1;
|
||
}
|
||
|
||
.price-large {
|
||
font-family: var(--font-heading);
|
||
font-size: var(--text-2xl);
|
||
font-weight: var(--font-bold);
|
||
color: var(--primary-600);
|
||
}
|
||
|
||
.price-period {
|
||
font-size: var(--text-sm);
|
||
color: var(--text-tertiary);
|
||
margin-top: var(--space-xs);
|
||
}
|
||
|
||
.action-buttons {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.gallery-section {
|
||
display: grid;
|
||
grid-template-columns: 2fr 1fr;
|
||
gap: var(--space-sm);
|
||
margin-bottom: var(--space-xl);
|
||
height: 400px;
|
||
}
|
||
|
||
.main-image {
|
||
border-radius: var(--radius-lg);
|
||
overflow: hidden;
|
||
height: 100%;
|
||
}
|
||
|
||
.gallery-image {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
cursor: pointer;
|
||
transition: transform 0.3s ease;
|
||
}
|
||
|
||
.gallery-image:hover {
|
||
transform: scale(1.02);
|
||
}
|
||
|
||
.thumbnails {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: var(--space-sm);
|
||
height: 100%;
|
||
}
|
||
|
||
.thumbnail {
|
||
position: relative;
|
||
border-radius: var(--radius-md);
|
||
overflow: hidden;
|
||
cursor: pointer;
|
||
height: calc(50% - var(--space-sm) / 2);
|
||
}
|
||
|
||
.thumbnail img {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
transition: transform 0.3s ease;
|
||
}
|
||
|
||
.thumbnail:hover img {
|
||
transform: scale(1.05);
|
||
}
|
||
|
||
.more-images {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: rgba(0, 0, 0, 0.7);
|
||
color: var(--text-inverse);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-weight: var(--font-bold);
|
||
font-size: var(--text-lg);
|
||
}
|
||
|
||
.content-grid {
|
||
display: grid;
|
||
grid-template-columns: 2fr 1fr;
|
||
gap: var(--space-xl);
|
||
align-items: start;
|
||
}
|
||
|
||
.content-main {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-xl);
|
||
}
|
||
|
||
.content-section {
|
||
background: var(--bg-primary);
|
||
border-radius: var(--radius-lg);
|
||
padding: var(--space-xl);
|
||
box-shadow: var(--shadow-sm);
|
||
border: 1px solid var(--border-light);
|
||
}
|
||
|
||
.section-title {
|
||
font-family: var(--font-heading);
|
||
font-size: var(--text-xl);
|
||
font-weight: var(--font-semibold);
|
||
color: var(--text-primary);
|
||
margin-bottom: var(--space-lg);
|
||
}
|
||
|
||
.object-description {
|
||
font-size: var(--text-lg);
|
||
line-height: var(--leading-relaxed);
|
||
color: var(--text-secondary);
|
||
margin: 0;
|
||
}
|
||
|
||
.amenities-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||
gap: var(--space-md);
|
||
}
|
||
|
||
.amenity-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-sm);
|
||
padding: var(--space-sm);
|
||
background: var(--bg-secondary);
|
||
border-radius: var(--radius-md);
|
||
}
|
||
|
||
.amenity-icon {
|
||
font-size: var(--text-lg);
|
||
}
|
||
|
||
.amenity-text {
|
||
font-weight: var(--font-medium);
|
||
color: var(--text-primary);
|
||
}
|
||
|
||
.contact-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-md);
|
||
}
|
||
|
||
.contact-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.contact-icon {
|
||
font-size: var(--text-lg);
|
||
width: 1.5rem;
|
||
}
|
||
|
||
.contact-link {
|
||
color: var(--primary-600);
|
||
text-decoration: none;
|
||
transition: color 0.3s ease;
|
||
}
|
||
|
||
.contact-link:hover {
|
||
color: var(--primary-700);
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.contact-text {
|
||
color: var(--text-primary);
|
||
}
|
||
|
||
.content-sidebar {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-lg);
|
||
position: sticky;
|
||
top: var(--space-xl);
|
||
}
|
||
|
||
.booking-card .card-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: var(--space-lg);
|
||
}
|
||
|
||
.card-title {
|
||
font-family: var(--font-heading);
|
||
font-size: var(--text-lg);
|
||
font-weight: var(--font-semibold);
|
||
color: var(--text-primary);
|
||
margin: 0;
|
||
}
|
||
|
||
.booking-form {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-lg);
|
||
}
|
||
|
||
.date-inputs {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.contact-actions {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.delete-btn {
|
||
color: var(--danger-500);
|
||
border-color: var(--danger-200);
|
||
}
|
||
|
||
.delete-btn:hover {
|
||
background: var(--danger-50);
|
||
border-color: var(--danger-500);
|
||
}
|
||
|
||
.loading-state,
|
||
.empty-state {
|
||
text-align: center;
|
||
padding: var(--space-2xl);
|
||
background: var(--bg-primary);
|
||
border-radius: var(--radius-lg);
|
||
border: 1px solid var(--border-light);
|
||
}
|
||
|
||
.loading-spinner {
|
||
width: 3rem;
|
||
height: 3rem;
|
||
border: 3px solid var(--border-light);
|
||
border-top: 3px solid var(--primary-500);
|
||
border-radius: 50%;
|
||
animation: spin 1s linear infinite;
|
||
margin: 0 auto var(--space-md);
|
||
}
|
||
|
||
.empty-icon {
|
||
font-size: 4rem;
|
||
margin-bottom: var(--space-lg);
|
||
opacity: 0.7;
|
||
}
|
||
|
||
@keyframes spin {
|
||
0% { transform: rotate(0deg); }
|
||
100% { transform: rotate(360deg); }
|
||
}
|
||
|
||
@media (max-width: 1024px) {
|
||
.content-grid {
|
||
grid-template-columns: 1fr;
|
||
gap: var(--space-lg);
|
||
}
|
||
|
||
.content-sidebar {
|
||
position: static;
|
||
}
|
||
|
||
.gallery-section {
|
||
height: 300px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.header-content {
|
||
grid-template-columns: 1fr;
|
||
gap: var(--space-lg);
|
||
}
|
||
|
||
.header-actions {
|
||
min-width: auto;
|
||
}
|
||
|
||
.gallery-section {
|
||
grid-template-columns: 1fr;
|
||
height: auto;
|
||
}
|
||
|
||
.thumbnails {
|
||
grid-template-columns: repeat(4, 1fr);
|
||
height: 100px;
|
||
}
|
||
|
||
.thumbnail {
|
||
height: 100px;
|
||
}
|
||
|
||
.page-title {
|
||
font-size: var(--text-2xl);
|
||
}
|
||
|
||
.amenities-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.page-header {
|
||
padding: var(--space-lg);
|
||
}
|
||
|
||
.object-meta {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.thumbnails {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
|
||
.thumbnail {
|
||
height: 80px;
|
||
}
|
||
|
||
.date-inputs {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
</style>
|