import { useMemo } from 'react'; import { Card, CardContent } from '@/components/ui/card'; import { Zap, Camera, FileText, MapPin, Phone, Clock, Check, Circle, } from 'lucide-react'; import { cn } from '@/lib/utils'; import { useTranslation } from '@/contexts/language'; export interface QualityCheckItem { id: string; label: string; description?: string; points: number; completed: boolean; icon: React.ComponentType<{ className?: string }>; } interface QualityMeterProps { type: 'spot' | 'shop'; // Form state checks hasLocation: boolean; hasPhotos: boolean; photoCount: number; hasDescription: boolean; descriptionLength: number; // Shop-specific hasPhone?: boolean; hasWebsite?: boolean; hasHours?: boolean; // Spot-specific hasSpotType?: boolean; className?: string; } export function QualityMeter({ type, hasLocation, hasPhotos, photoCount, hasDescription, descriptionLength, hasPhone, hasWebsite, hasHours, hasSpotType, className, }: QualityMeterProps) { const { t } = useTranslation(); const checks = useMemo(() => { const items: QualityCheckItem[] = [ { id: 'location', label: t('miscUi.qualityLocationAdded'), points: 20, completed: hasLocation, icon: MapPin, }, { id: 'photo1', label: t('miscUi.qualityOnePhoto'), points: 20, completed: hasPhotos, icon: Camera, }, { id: 'photo3', label: t('miscUi.qualityThreePhotos'), description: t('miscUi.qualityMoreAngles'), points: 15, completed: photoCount >= 3, icon: Camera, }, { id: 'description', label: t('miscUi.qualityDescription'), points: 15, completed: hasDescription && descriptionLength >= 20, icon: FileText, }, { id: 'description-detailed', label: t('miscUi.qualityDetailedDesc'), points: 10, completed: descriptionLength >= 100, icon: FileText, }, ]; if (type === 'shop') { items.push( { id: 'contact', label: t('miscUi.qualityContact'), description: t('miscUi.qualityPhoneOrWebsite'), points: 10, completed: !!hasPhone || !!hasWebsite, icon: Phone, }, { id: 'hours', label: t('miscUi.qualityHours'), points: 10, completed: !!hasHours, icon: Clock, } ); } else { items.push({ id: 'spot-type', label: t('miscUi.qualitySpotType'), points: 10, completed: !!hasSpotType, icon: MapPin, }); } return items; }, [type, hasLocation, hasPhotos, photoCount, hasDescription, descriptionLength, hasPhone, hasWebsite, hasHours, hasSpotType, t]); const { score, maxScore } = useMemo(() => { const completed = checks.filter(c => c.completed); const total = checks.reduce((sum, c) => sum + c.points, 0); const current = completed.reduce((sum, c) => sum + c.points, 0); return { score: current, maxScore: total, completedItems: completed.length, totalItems: checks.length, }; }, [checks]); const percentage = Math.round((score / maxScore) * 100); const getScoreColor = () => { if (percentage >= 80) return 'text-green-400'; if (percentage >= 50) return 'text-[#ccff00]'; if (percentage >= 30) return 'text-yellow-400'; return 'text-orange-400'; }; const getProgressColor = () => { if (percentage >= 80) return 'bg-green-500'; if (percentage >= 50) return 'bg-[#ccff00]'; if (percentage >= 30) return 'bg-yellow-500'; return 'bg-orange-500'; }; const getScoreLabel = () => { if (percentage >= 80) return t('miscUi.qualityExcellent'); if (percentage >= 50) return t('miscUi.qualityGood'); if (percentage >= 30) return t('miscUi.qualityBasic'); return t('miscUi.qualityGettingStarted'); }; return (
{t('miscUi.earningPotential')}
{getScoreLabel()} {percentage}%
{/* Progress Bar */}
{/* Checklist */}
{checks.map((check) => { const Icon = check.icon; return (
{check.completed ? ( ) : ( )}
{check.label} +{check.points}%
); })}
{/* Tip */}

💡 Higher quality = More zaps from the community!

); }