mojmajstor/components/review-card.tsx
echo c700d139f7 feat: Phase 6 - reviews and ratings with computed fields
- Review create mutation with auth, customer-only role check,
  self-review prevention, and ad ratingAvg/reviewCount recomputation
- ReviewCard component: reviewer avatar, name, relative time in
  Macedonian, star rating, comment
- Create review screen: interactive 5-star selector (Многу лошо–Отлично),
  comment field, auth gate, submit and navigate back
- Ad detail: review section listing all reviews with reviewer names,
  overall rating summary with count, 'Напиши оценка' button
- AdCard: rating stars shown next to title when ad has reviews

All UI text in Macedonian. TypeScript clean, Convex functions deployed.
2026-05-29 18:41:07 +02:00

70 lines
2.3 KiB
TypeScript

import { View, Text } from "react-native";
import { useTheme } from "./theme";
import { Avatar } from "./ui/avatar";
import { Rating } from "./ui/rating";
function formatTimeAgo(timestamp: number): string {
const now = Date.now();
const diff = now - timestamp;
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
const months = Math.floor(days / 30);
const years = Math.floor(days / 365);
if (years > 0) return `пред ${years} ${years === 1 ? "година" : "години"}`;
if (months > 0) return `пред ${months} ${months === 1 ? "месец" : "месеци"}`;
if (days > 0) return `пред ${days} ${days === 1 ? "ден" : "денови"}`;
if (hours > 0) return `пред ${hours} ${hours === 1 ? "час" : "часа"}`;
if (minutes > 0) return `пред ${minutes} ${minutes === 1 ? "минута" : "минути"}`;
return "пред малку";
}
interface ReviewCardProps {
review: {
_id: string;
rating: number;
comment?: string;
createdAt: number;
};
customerName: string;
customerAvatarId?: string;
}
export function ReviewCard({ review, customerName, customerAvatarId }: ReviewCardProps) {
const theme = useTheme();
return (
<View
style={{
backgroundColor: theme.colors.card,
borderRadius: theme.radius.lg,
padding: theme.spacing.md,
borderWidth: 1,
borderColor: theme.colors.border,
gap: theme.spacing.sm,
}}
>
<View style={{ flexDirection: "row", alignItems: "center", gap: theme.spacing.sm }}>
<Avatar uri={customerAvatarId ?? null} name={customerName} size={36} />
<View style={{ flex: 1 }}>
<Text style={{ fontSize: 14, fontWeight: "600", color: theme.colors.text }}>
{customerName}
</Text>
<Text style={{ fontSize: 12, color: theme.colors.textTertiary }}>
{formatTimeAgo(review.createdAt)}
</Text>
</View>
<Rating value={review.rating} size={16} />
</View>
{review.comment ? (
<Text style={{ fontSize: 14, color: theme.colors.textSecondary, lineHeight: 20 }}>
{review.comment}
</Text>
) : null}
</View>
);
}