Files
aerbim-ht-monitor/frontend/app/(protected)/objects/page.tsx
2025-10-15 19:49:19 +03:00

123 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import React, { useState, useEffect } from 'react'
import ObjectGallery from '../../../components/objects/ObjectGallery'
import { ObjectData } from '../../../components/objects/ObjectCard'
import Sidebar from '../../../components/ui/Sidebar'
// Универсальная функция для преобразования объекта из бэкенда в ObjectData
const transformRawToObjectData = (raw: any): ObjectData => {
const rawId = raw?.id ?? raw?.object_id ?? raw?.uuid ?? raw?.name
const object_id = typeof rawId === 'number' ? `object_${rawId}` : String(rawId ?? '')
return {
object_id,
title: raw?.title ?? `Объект ${object_id}`,
description: raw?.description ?? `Описание объекта ${raw?.title ?? object_id}`,
image: raw?.image ?? '/images/test_image.png',
location: raw?.location ?? raw?.address ?? 'Не указано',
floors: Number(raw?.floors ?? 0),
area: String(raw?.area ?? ''),
type: raw?.type ?? 'object',
status: raw?.status ?? 'active',
}
}
const ObjectsPage: React.FC = () => {
const [objects, setObjects] = useState<ObjectData[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const [selectedObjectId, setSelectedObjectId] = useState<string | null>(null)
useEffect(() => {
const loadData = async () => {
setLoading(true)
setError(null)
try {
const url = '/api/get-objects'
const res = await fetch(url, { cache: 'no-store' })
const payloadText = await res.text()
let payload: any
try { payload = JSON.parse(payloadText) } catch { payload = payloadText }
console.log('[ObjectsPage] GET /api/get-objects', { status: res.status, payload })
if (!res.ok) {
throw new Error(typeof payload === 'string' ? payload : (payload?.error || 'Не удалось получить данные объектов'))
}
const data = (payload?.data ?? payload) as any
let rawObjectsArray: any[] = []
if (Array.isArray(data)) {
rawObjectsArray = data
} else if (Array.isArray(data?.objects)) {
rawObjectsArray = data.objects
} else if (data && typeof data === 'object') {
// если приходит как map { id: obj }
rawObjectsArray = Object.values(data)
}
const transformedObjects = rawObjectsArray.map(transformRawToObjectData)
setObjects(transformedObjects)
} catch (err: any) {
console.error('Ошибка при загрузке данных объектов:', err)
setError(err?.message || 'Произошла неизвестная ошибка')
} finally {
setLoading(false)
}
}
loadData()
}, [])
const handleObjectSelect = (objectId: string) => {
console.log('Object selected:', objectId)
setSelectedObjectId(objectId)
}
if (loading) {
return (
<div className="flex items-center justify-center min-h-screen bg-[#0e111a]">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500 mx-auto mb-4"></div>
<p className="text-white">Загрузка объектов...</p>
</div>
</div>
)
}
if (error) {
return (
<div className="flex items-center justify-center min-h-screen bg-[#0e111a]">
<div className="text-center">
<div className="text-red-500 mb-4">
<svg className="w-12 h-12 mx-auto" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
</svg>
</div>
<h3 className="text-lg font-medium text-white mb-2">Ошибка загрузки</h3>
<p className="text-[#71717a] mb-4">{error}</p>
<button
onClick={() => window.location.reload()}
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-[#3193f5] hover:bg-[#2563eb] focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50 transition-colors duration-200"
>
Попробовать снова
</button>
</div>
</div>
)
}
return (
<div className="flex h-screen bg-[#0e111a]">
<Sidebar activeItem={null} />
<div className="flex-1 overflow-hidden">
<ObjectGallery
objects={objects}
title="Объекты"
onObjectSelect={handleObjectSelect}
selectedObjectId={selectedObjectId}
/>
</div>
</div>
)
}
export default ObjectsPage