mojmajstor/components/ad-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

59 lines
1.9 KiB
TypeScript

import { View, Text, Pressable } from "react-native";
import { Link } from "expo-router";
import { useTheme } from "./theme";
import { Badge } from "./ui/badge";
import { Rating } from "./ui/rating";
import { getCategoryName } from "../lib/constants";
interface AdCardProps {
ad: {
_id: string;
title: string;
category: string;
location: string;
priceRange?: string;
ratingAvg?: number;
reviewCount: number;
};
}
export function AdCard({ ad }: AdCardProps) {
const theme = useTheme();
const categoryName = getCategoryName(ad.category);
return (
<Link href={`/ad/${ad._id}` as any} asChild>
<Pressable
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", justifyContent: "space-between", alignItems: "flex-start" }}>
<View style={{ flex: 1, gap: 2 }}>
<Text style={{ fontSize: 16, fontWeight: "600", color: theme.colors.text }}>
{ad.title}
</Text>
{ad.ratingAvg != null && ad.ratingAvg > 0 && (
<Rating value={ad.ratingAvg} count={ad.reviewCount} size={14} />
)}
</View>
{ad.priceRange && (
<Text style={{ fontSize: 14, fontWeight: "600", color: theme.colors.primary, marginLeft: 8 }}>
{ad.priceRange}
</Text>
)}
</View>
<View style={{ flexDirection: "row", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
<Badge label={categoryName} variant="primary" />
<Text style={{ fontSize: 13, color: theme.colors.textTertiary }}>📍 {ad.location}</Text>
</View>
</Pressable>
</Link>
);
}