All files / src/components/company-profile TestimonialsSection.tsx

100% Statements 5/5
94.44% Branches 17/18
100% Functions 5/5
100% Lines 5/5

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123                                                        266x                                                         46x                                               220x                                   1x             3x                                
import { MessageSquare, Plus, Edit2, Trash2 } from "lucide-react";
import {
	Card,
	CardContent,
	CardHeader,
	CardTitle,
	CardDescription,
} from "../ui/card";
import { Button } from "../ui/button";
import type { ProTestimonial } from "../../lib/api";
 
interface TestimonialsSectionProps {
	testimonials: ProTestimonial[];
	onAdd: () => void;
	onEdit: (testimonial: ProTestimonial) => void;
	onDelete: (id: number) => void;
	/** #424: gate Add/Edit/Delete on caller's edit permission. Default
	 * `true` preserves admin-page behavior. */
	canEdit?: boolean;
}
 
export function TestimonialsSection({
	testimonials,
	onAdd,
	onEdit,
	onDelete,
	canEdit = true,
}: TestimonialsSectionProps) {
	return (
		<Card>
			<CardHeader className="flex flex-row items-center justify-between">
				<div>
					<CardTitle className="flex items-center gap-2">
						<MessageSquare className="h-5 w-5" />
						Customer Reviews
					</CardTitle>
					<CardDescription>
						Share customer success stories (up to 10)
					</CardDescription>
				</div>
				{canEdit && testimonials.length < 10 && (
					<Button variant="outline" size="sm" onClick={onAdd}>
						<Plus className="h-4 w-4 mr-1" />
						Add
					</Button>
				)}
			</CardHeader>
			<CardContent>
				{testimonials.length === 0 ? (
					<div className="text-center py-8 text-foreground-muted">
						<MessageSquare className="h-12 w-12 mx-auto mb-2 text-foreground-subtle" />
						<p>No testimonials added yet</p>
						<p className="text-sm">Customer reviews build credibility</p>
					</div>
				) : (
					<div className="space-y-4">
						{testimonials.map((testimonial) => (
							<div key={testimonial.id} className="p-4 border rounded-lg">
								<div className="flex items-start justify-between">
									<div className="flex-1">
										<p className="text-foreground-default italic">
											&ldquo;{testimonial.reviewText}&rdquo;
										</p>
										<div className="mt-2 flex items-center gap-2">
											<span className="font-medium">
												{testimonial.customerName}
											</span>
											{testimonial.customerLocation && (
												<span className="text-sm text-foreground-muted">
													from {testimonial.customerLocation}
												</span>
											)}
											{testimonial.projectType && (
												<span className="text-sm text-foreground-subtle">
													• {testimonial.projectType}
												</span>
											)}
										</div>
										{testimonial.rating && (
											<div className="mt-1 flex">
												{[1, 2, 3, 4, 5].map((star) => (
													<span
														key={`star-${testimonial.id}-${star}`}
														className={
															star <= (testimonial.rating ?? 0)
																? "text-rating"
																: "text-foreground-subtle"
														}
													>
														★
													</span>
												))}
											</div>
										)}
									</div>
									{canEdit && (
										<div className="flex gap-2 ml-4">
											<button
												type="button"
												onClick={() => onEdit(testimonial)}
												className="p-1 text-foreground-subtle hover:text-info"
											>
												<Edit2 className="h-4 w-4" />
											</button>
											<button
												type="button"
												onClick={() => onDelete(testimonial.id)}
												className="p-1 text-foreground-subtle hover:text-error"
											>
												<Trash2 className="h-4 w-4" />
											</button>
										</div>
									)}
								</div>
							</div>
						))}
					</div>
				)}
			</CardContent>
		</Card>
	);
}