146 lines
3.5 KiB
Vue
146 lines
3.5 KiB
Vue
<template>
|
||
<div class="my-objects">
|
||
<section class="page-hero">
|
||
<div class="container">
|
||
<h1>Мои объекты</h1>
|
||
<NuxtLink to="/objects/create" class="btn btn--primary btn--md">
|
||
Добавить объект
|
||
</NuxtLink>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="section">
|
||
<div class="container">
|
||
<div v-if="loading" class="my-objects__grid">
|
||
<div v-for="n in 3" :key="n" class="card">
|
||
<div class="skeleton" style="height: 160px" />
|
||
<div style="padding: 16px">
|
||
<div class="skeleton" style="height: 20px; width: 80%; margin-bottom: 8px" />
|
||
<div class="skeleton" style="height: 16px; width: 60%" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div v-else-if="objects.length" class="my-objects__grid">
|
||
<NuxtLink
|
||
v-for="obj in objects"
|
||
:key="obj.id"
|
||
:to="`/objects/edit/${obj.id}`"
|
||
class="card object-card"
|
||
>
|
||
<div class="object-card__image">
|
||
<img
|
||
v-if="obj.images?.[0]"
|
||
:src="obj.images[0]"
|
||
:alt="obj.title"
|
||
/>
|
||
<div v-else class="object-card__placeholder">
|
||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none">
|
||
<rect x="3" y="3" width="18" height="18" rx="2" stroke="currentColor" stroke-width="2"/>
|
||
<circle cx="8.5" cy="8.5" r="1.5" stroke="currentColor" stroke-width="2"/>
|
||
<path d="M21 15l-5-5L5 21" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
<div class="object-card__info">
|
||
<h5>{{ obj.title }}</h5>
|
||
<p class="small-text">{{ obj.status || 'Активен' }}</p>
|
||
</div>
|
||
</NuxtLink>
|
||
</div>
|
||
|
||
<div v-else class="my-objects__empty">
|
||
<p class="body-text--gray">У вас пока нет объектов</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
definePageMeta({
|
||
title: 'Мои объекты',
|
||
middleware: 'auth',
|
||
})
|
||
|
||
const objectsStore = useObjectsStore()
|
||
const { objects, loading } = storeToRefs(objectsStore)
|
||
|
||
onMounted(async () => {
|
||
const { user } = useAuth()
|
||
if (user.value?.id) {
|
||
try {
|
||
const api = useApi()
|
||
const response = await api.get<{ items: typeof objects.value }>(`/objects/owner/${user.value.id}`)
|
||
objectsStore.objects = response.items ?? []
|
||
} catch {
|
||
// ignore
|
||
}
|
||
}
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
.page-hero {
|
||
background: var(--color-primary);
|
||
padding: 60px 0;
|
||
text-align: center;
|
||
color: var(--color-text-white);
|
||
}
|
||
|
||
.page-hero h1 {
|
||
color: var(--color-text-white);
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.my-objects__grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 24px;
|
||
}
|
||
|
||
.object-card {
|
||
cursor: pointer;
|
||
}
|
||
|
||
.object-card__image {
|
||
height: 160px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.object-card__image img {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.object-card__placeholder {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: var(--color-bg-gray);
|
||
color: var(--color-text-gray);
|
||
}
|
||
|
||
.object-card__info {
|
||
padding: 16px;
|
||
}
|
||
|
||
.object-card__info h5 {
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.my-objects__empty {
|
||
text-align: center;
|
||
padding: 60px 0;
|
||
}
|
||
|
||
@media (max-width: 744px) {
|
||
.my-objects__grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
</style>
|