import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'; import { Image } from 'expo-image'; import { Ionicons } from '@expo/vector-icons'; import { useTranslation } from 'react-i18next'; import { useColors } from '../../lib/theme'; export type Room = { id: string; name: string; description?: string | null; isPublic: boolean; isDefault: boolean; memberCount: number; isMember: boolean; avatarUrl?: string | null; lastMessage?: { content: string; createdAt: string; senderName: string } | null; }; type Props = { room: Room; onPress: () => void; }; function formatTime(ts: string, justNow: string) { const diff = Date.now() - new Date(ts).getTime(); if (diff < 60_000) return justNow; if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}m`; if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)}h`; return new Date(ts).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' }); } export function RoomCard({ room, onPress }: Props) { const { t } = useTranslation(); const colors = useColors(); const styles = makeStyles(colors); const initials = room.name .split(' ') .slice(0, 2) .map((w) => w[0]?.toUpperCase() ?? '') .join(''); return ( {room.avatarUrl ? ( ) : !room.isPublic ? ( {initials} ) : ( )} {room.name} {room.isDefault && ( Standard )} {room.lastMessage && ( {formatTime(room.lastMessage.createdAt, t('chat.just_now'))} )} {room.lastMessage ? ( {room.lastMessage.senderName}: {room.lastMessage.content} ) : room.description ? ( {room.description} ) : null} {room.memberCount} {!room.isMember && ( {t('chat.join')} )} ); } function makeStyles(colors: ReturnType) { return StyleSheet.create({ row: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 12, backgroundColor: colors.bg, borderBottomWidth: StyleSheet.hairlineWidth, borderBottomColor: colors.border, minHeight: 68, }, avatar: { width: 48, height: 48, borderRadius: 24, alignItems: 'center', justifyContent: 'center', overflow: 'hidden', marginRight: 12, flexShrink: 0, }, avatarImg: { width: 48, height: 48, }, avatarInitials: { fontSize: 15, fontFamily: 'Nunito_700Bold', color: colors.textMuted, }, info: { flex: 1, minWidth: 0, }, headerRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 3, }, nameWrap: { flex: 1, flexDirection: 'row', alignItems: 'center', gap: 6, minWidth: 0, }, metaRight: { marginLeft: 8, flexShrink: 0, }, footerRow: { flexDirection: 'row', alignItems: 'center', }, footerTextWrap: { flex: 1, minWidth: 0, }, footerRight: { flexDirection: 'row', alignItems: 'center', gap: 6, marginLeft: 8, flexShrink: 0, }, name: { fontSize: 15, fontFamily: 'Nunito_700Bold', color: colors.text, flexShrink: 1, }, defaultBadge: { paddingHorizontal: 6, paddingVertical: 2, backgroundColor: '#EFF6FF', borderRadius: 6, flexShrink: 0, }, defaultBadgeText: { fontSize: 9, fontFamily: 'Nunito_700Bold', color: '#3B82F6', }, lastMessage: { fontSize: 13, fontFamily: 'Nunito_400Regular', color: colors.textMuted, }, senderName: { fontFamily: 'Nunito_600SemiBold', color: colors.textMuted, }, description: { fontSize: 13, fontFamily: 'Nunito_400Regular', color: colors.textMuted, }, metaPill: { flexDirection: 'row', alignItems: 'center', gap: 3, paddingHorizontal: 6, paddingVertical: 3, borderRadius: 8, backgroundColor: colors.surfaceElevated, }, memberCount: { fontSize: 11, fontFamily: 'Nunito_700Bold', color: colors.textMuted, }, time: { fontSize: 11, fontFamily: 'Nunito_500Medium', color: colors.textMuted, }, joinBadge: { paddingHorizontal: 8, paddingVertical: 3, backgroundColor: '#EFF6FF', borderRadius: 10, }, joinBadgeText: { fontSize: 11, fontFamily: 'Nunito_700Bold', color: '#007AFF', }, }); }