Разработка интерфейса фронт
This commit is contained in:
103
frontend/components/objects/ObjectCard.tsx
Normal file
103
frontend/components/objects/ObjectCard.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
import Image from 'next/image'
|
||||
import { useNavigationService } from '@/services/navigationService'
|
||||
interface ObjectData {
|
||||
object_id: string
|
||||
title: string
|
||||
description: string
|
||||
image: string
|
||||
location: string
|
||||
floors?: number
|
||||
area?: string
|
||||
type?: string
|
||||
status?: string
|
||||
}
|
||||
|
||||
interface ObjectCardProps {
|
||||
object: ObjectData
|
||||
onSelect?: (objectId: string) => void
|
||||
isSelected?: boolean
|
||||
}
|
||||
|
||||
// Иконка редактирования
|
||||
const EditIcon = ({ className }: { className?: string }) => (
|
||||
<svg className={className} fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" />
|
||||
</svg>
|
||||
)
|
||||
|
||||
const ObjectCard: React.FC<ObjectCardProps> = ({ object, onSelect, isSelected = false }) => {
|
||||
const navigationService = useNavigationService()
|
||||
|
||||
const handleCardClick = () => {
|
||||
if (onSelect) {
|
||||
onSelect(object.object_id)
|
||||
}
|
||||
// Навигация к дашборду с выбранным объектом
|
||||
navigationService.selectObjectAndGoToDashboard(object.object_id, object.title)
|
||||
}
|
||||
|
||||
const handleEditClick = (e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
console.log('Edit object:', object.object_id)
|
||||
// Логика редактирования объекта
|
||||
}
|
||||
|
||||
return (
|
||||
<article
|
||||
className={`flex flex-col w-full min-h-[414px] h-[414px] sm:h-auto sm:min-h-[350px] items-start gap-4 p-4 sm:p-6 relative bg-[#161824] rounded-[20px] overflow-hidden cursor-pointer transition-all duration-200 hover:bg-[#1a1d2e] ${
|
||||
isSelected ? 'ring-2 ring-blue-500' : ''
|
||||
}`}
|
||||
onClick={handleCardClick}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
handleCardClick()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<header className="flex flex-col sm:flex-row items-start sm:items-center gap-3 sm:gap-2 relative self-stretch w-full flex-[0_0_auto]">
|
||||
<div className="flex-col items-start flex-1 grow flex relative min-w-0">
|
||||
<h2 className="self-stretch mt-[-1.00px] font-medium text-white text-lg leading-7 relative tracking-[0] break-words">
|
||||
{object.title}
|
||||
</h2>
|
||||
<p className="self-stretch font-normal text-[#71717a] text-sm leading-5 relative tracking-[0] break-words">
|
||||
{object.description}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
className="inline-flex flex-shrink-0 bg-[#3193f5] h-10 items-center justify-center gap-2 px-3 sm:px-4 py-2 relative rounded-md transition-colors duration-200 hover:bg-[#2563eb] focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50 w-full sm:w-auto"
|
||||
aria-label={`Изменить ${object.title}`}
|
||||
onClick={handleEditClick}
|
||||
>
|
||||
<EditIcon className="!relative !w-4 !h-4 text-white flex-shrink-0" />
|
||||
<span className="font-medium text-white text-sm leading-5 relative tracking-[0] sm:whitespace-nowrap">
|
||||
Изменить
|
||||
</span>
|
||||
</button>
|
||||
</header>
|
||||
|
||||
{/* Изображение объекта */}
|
||||
<div className="relative flex-1 self-stretch w-full grow bg-[#f1f1f1] rounded-lg overflow-hidden min-h-[200px] sm:min-h-[250px]">
|
||||
<Image
|
||||
className="absolute w-full h-full top-0 left-0 object-cover"
|
||||
alt={object.title}
|
||||
src={object.image}
|
||||
fill
|
||||
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
||||
onError={(e) => {
|
||||
// Заглушка при ошибке загрузки изображения
|
||||
const target = e.target as HTMLImageElement
|
||||
target.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDUyIiBoZWlnaHQ9IjMwMiIgdmlld0JveD0iMCAwIDQ1MiAzMDIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSI0NTIiIGhlaWdodD0iMzAyIiBmaWxsPSIjRjFGMUYxIi8+CjxwYXRoIGQ9Ik0yMjYgMTUxTDI0NiAxMzFMMjY2IDE1MUwyNDYgMTcxTDIyNiAxNTFaIiBmaWxsPSIjOTk5OTk5Ii8+Cjx0ZXh0IHg9IjIyNiIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjOTk5OTk5IiBmb250LXNpemU9IjE0Ij7QntCx0YrQtdC60YI8L3RleHQ+Cjwvc3ZnPgo='
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
|
||||
export default ObjectCard
|
||||
export type { ObjectData, ObjectCardProps }
|
||||
Reference in New Issue
Block a user