e95490eb72
- Grundriss (FloorPlanSection): PropertyUnit.floorPlanUrl?, Property.floorPlanUrl?; FloorPlanSection in MatchDetail + PropertyDetail; FloorPlanUrlSection in NewListing-Formular - Listenansicht (MatchCardCompact): horizontales Layout mit 120px Bildstreifen, Score-Badge, Asset-Label-Overlay, alle 3 grünen Punkte, Anfrage-Button - Light Industrial → "Gewerbe" überall (NeedInput, NeedCardPreview, CriteriaReviewPanel, newListingConstants, MyListings, propertyHelpers) - "Zum Originalinserat"-Button nur bei Maison-Work-Objekten - Image-Pool: propertyImageResolver mit sequentiellem Pool-Index (keine doppelten Bilder), nur Innenaufnahmen, rotate()-Trick für Sub-Pools - Overlay-Labels (Objekttyp + Stadtteil) in LocationPreview + IntelligenceMatchCard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
72 lines
3.5 KiB
TypeScript
72 lines
3.5 KiB
TypeScript
import { Box, Typography } from '@mui/material'
|
|
import { Bot, Building2, FileText } from 'lucide-react'
|
|
import { DS_COLORS, DS_TEXT, DS_BG, DS_BORDER } from '../../lib/ds'
|
|
import type { InquiryMessage } from '../../domain/inquiry'
|
|
|
|
export function AnfragenMessageBubble({ msg, currentUserName }: { msg: InquiryMessage; currentUserName?: string }) {
|
|
const isOwnMessage = msg.senderType === 'tenant'
|
|
const isAI = msg.senderType === 'ai'
|
|
const time = new Date(msg.createdAt).toLocaleTimeString('de-CH', { hour: '2-digit', minute: '2-digit' })
|
|
const date = new Date(msg.createdAt).toLocaleDateString('de-CH', { day: '2-digit', month: '2-digit' })
|
|
|
|
return (
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: isOwnMessage ? 'flex-end' : 'flex-start', mb: 0.5 }}>
|
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, mb: 0.375 }}>
|
|
{!isOwnMessage && isAI && <Bot size={11} color={DS_TEXT.signal} />}
|
|
{!isOwnMessage && msg.senderType === 'supply_user' && <Building2 size={11} color={DS_TEXT.muted} />}
|
|
<Typography variant="caption" color="text.secondary" sx={{ fontSize: '0.7rem' }}>
|
|
{isOwnMessage && currentUserName ? currentUserName : msg.senderName} · {date} {time}
|
|
</Typography>
|
|
</Box>
|
|
<Box
|
|
sx={{
|
|
maxWidth: { xs: '88%', md: '72%' },
|
|
px: 2, py: 1.25,
|
|
borderRadius: isOwnMessage ? '18px 18px 4px 18px' : '18px 18px 18px 4px',
|
|
bgcolor: isOwnMessage ? 'primary.main' : isAI ? DS_COLORS.futureCard.controlled.headerBg : 'white',
|
|
border: isOwnMessage ? 'none' : isAI ? `1px solid ${DS_COLORS.futureCard.controlled.border}` : `1px solid ${DS_BORDER.default}`,
|
|
boxShadow: isOwnMessage ? '0 2px 6px rgba(30,58,95,0.2)' : '0 1px 2px rgba(0,0,0,0.06)',
|
|
}}
|
|
>
|
|
<Typography
|
|
variant="body2"
|
|
sx={{
|
|
color: isOwnMessage ? 'white' : isAI ? DS_COLORS.futureCard.controlled.badgeText : DS_TEXT.primary,
|
|
whiteSpace: 'pre-wrap', lineHeight: 1.65, fontSize: '0.875rem',
|
|
}}
|
|
>
|
|
{msg.body}
|
|
</Typography>
|
|
{msg.attachments.length > 0 && (
|
|
<Box sx={{ mt: 1, display: 'flex', flexDirection: 'column', gap: 0.5 }}>
|
|
{msg.attachments.map(att => (
|
|
<Box
|
|
key={att.id}
|
|
sx={{
|
|
display: 'flex', alignItems: 'center', gap: 1,
|
|
px: 1.5, py: 0.75,
|
|
bgcolor: isOwnMessage ? 'rgba(255,255,255,0.12)' : DS_BG.subtle,
|
|
borderRadius: 1.5, cursor: 'pointer',
|
|
'&:hover': { bgcolor: isOwnMessage ? 'rgba(255,255,255,0.2)' : DS_BG.muted },
|
|
}}
|
|
>
|
|
<FileText size={13} color={isOwnMessage ? 'rgba(255,255,255,0.75)' : DS_TEXT.muted} />
|
|
<Typography variant="caption" sx={{ color: isOwnMessage ? 'rgba(255,255,255,0.9)' : DS_TEXT.secondary, flex: 1 }} noWrap>
|
|
{att.fileName}
|
|
</Typography>
|
|
{att.fileSize && (
|
|
<Typography variant="caption" sx={{ color: isOwnMessage ? 'rgba(255,255,255,0.5)' : DS_TEXT.disabled, flexShrink: 0 }}>
|
|
{att.fileSize < 1024 * 1024
|
|
? `${Math.round(att.fileSize / 1024)} KB`
|
|
: `${(att.fileSize / 1024 / 1024).toFixed(1)} MB`}
|
|
</Typography>
|
|
)}
|
|
</Box>
|
|
))}
|
|
</Box>
|
|
)}
|
|
</Box>
|
|
</Box>
|
|
)
|
|
}
|