import React, { useState, useEffect } from 'react'; import { View, Text, ScrollView, StyleSheet, Pressable, Image, Alert, FlatList, } from 'react-native'; import { useRoute, useNavigation } from '@react-navigation/native'; import { StackNavigationProp } from '@react-navigation/stack'; import { RootStackParamList } from '../navigation/types'; import { supabase, isSupabaseConfigured } from '../services/supabase'; import { COLORS, SIZES, FONTS, SHADOWS } from '../constants/theme'; import { Barber, Review, Booking } from '../types'; import ReviewCard from '../components/ReviewCard'; import BookingCard from '../components/BookingCard'; const BarberDetailScreen: React.FC = () => { const route = useRoute(); const navigation = useNavigation>(); const { barberId } = route.params as { barberId: string }; const [barber, setBarber] = useState(null); const [reviews, setReviews] = useState([]); const [bookings, setBookings] = useState([]); const [loading, setLoading] = useState(true); const [activeTab, setActiveTab] = useState<'reviews' | 'availability'>('reviews'); useEffect(() => { loadBarberDetails(); }, [barberId]); const loadBarberDetails = async () => { try { if (!isSupabaseConfigured) { // Demo mode - use mock data const { mockBarbers, mockReviews } = await import('../data/mockData'); const barber = mockBarbers.find(b => b.id === barberId); if (barber) { setBarber(barber); // Load barber-specific reviews const barberReviews = mockReviews.filter(r => r.barber_id === barberId); setReviews(barberReviews); // Mock bookings for demo setBookings([]); } setLoading(false); return; } const [barberRes, reviewsRes, bookingsRes] = await Promise.all([ supabase .from('barbers') .select(` *, user:users(name, photo, email, phone) `) .eq('id', barberId) .single(), supabase .from('reviews') .select(` *, user:users(name, photo) `) .eq('barber_id', barberId) .order('created_at', { ascending: false }), supabase .from('bookings') .select(` *, service:services(name, price), customer:users(name) `) .eq('barber_id', barberId) .eq('status', 'completed') .order('booking_date', { ascending: false }) .limit(10) ]); if (barberRes.data) setBarber(barberRes.data); if (reviewsRes.data) setReviews(reviewsRes.data); if (bookingsRes.data) setBookings(bookingsRes.data); } catch (error) { console.error('Erro ao carregar detalhes do barbeiro:', error); Alert.alert('Erro', 'Falha ao carregar detalhes do barbeiro'); } finally { setLoading(false); } }; const handleBookNow = () => { Alert.alert( '👨‍💼 Marcar com Barbeiro', `Vou marcar com: ${barber?.user?.name}`, [ { text: 'Cancelar', style: 'cancel', }, { text: 'Confirmar', onPress: () => { Alert.alert( '✅ Barbeiro Selecionado', `${barber?.user?.name} foi selecionado para a sua marcação.\n\nContinue para escolher serviço, data e horário.`, [ { text: 'OK', onPress: () => navigation.navigate('Booking'), }, ] ); }, }, ] ); }; const renderStars = (rating: number) => { const stars = []; const fullStars = Math.floor(rating); for (let i = 0; i < fullStars; i++) { stars.push( ); } const emptyStars = 5 - fullStars; for (let i = 0; i < emptyStars; i++) { stars.push( ); } return stars; }; const renderAvailability = () => { if (!barber?.availability) return null; const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; return ( {days.map((day) => { const timeSlots = barber.availability[day.toLowerCase()] || []; return ( {day} {timeSlots.length > 0 ? ( timeSlots.map((time, index) => ( {time} )) ) : ( Fechado )} ); })} ); }; if (loading) { return ( A carregar... ); } if (!barber) { return ( Barbeiro não encontrado ); } return ( {/* Barber Header */} {barber.user?.name} {barber.specialty} {renderStars(barber.rating)} {barber.rating.toFixed(1)} {/* Bio */} Sobre {barber.bio} {/* Contact Info */} Contacto 📧 {barber.user?.email} 📱 {barber.user?.phone} {/* Book Button */} [styles.bookButton, pressed && styles.bookButtonPressed]} onPress={handleBookNow} > Marcar Horário {/* Tabs */} [ styles.tab, activeTab === 'reviews' && styles.activeTab, pressed && styles.tabPressed ]} onPress={() => setActiveTab('reviews')} > Avaliações ({reviews.length}) [ styles.tab, activeTab === 'availability' && styles.activeTab, pressed && styles.tabPressed ]} onPress={() => setActiveTab('availability')} > Disponibilidade {/* Tab Content */} {activeTab === 'reviews' ? ( <> {reviews.length === 0 ? ( Sem avaliações ) : ( reviews.map((review) => ( )) )} ) : ( renderAvailability() )} ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: COLORS.background, }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, loadingText: { ...FONTS.body, color: COLORS.textSecondary, }, errorContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, errorText: { ...FONTS.body, color: COLORS.error, }, header: { flexDirection: 'row', padding: SIZES.padding, backgroundColor: COLORS.surface, borderBottomWidth: 1, borderBottomColor: COLORS.border, }, avatar: { width: 100, height: 100, borderRadius: 50, marginRight: SIZES.margin, }, barberInfo: { flex: 1, }, name: { ...FONTS.h1, color: COLORS.text, marginBottom: SIZES.base / 2, }, specialty: { ...FONTS.h3, color: COLORS.primary, marginBottom: SIZES.base, }, ratingContainer: { flexDirection: 'row', alignItems: 'center', }, stars: { flexDirection: 'row', marginRight: SIZES.base, }, star: { color: COLORS.primary, fontSize: 18, }, emptyStar: { color: COLORS.border, }, rating: { ...FONTS.h3, color: COLORS.text, }, bioSection: { padding: SIZES.padding, }, sectionTitle: { ...FONTS.h2, color: COLORS.text, marginBottom: SIZES.margin, }, bio: { ...FONTS.body, color: COLORS.textSecondary, lineHeight: 24, }, contactSection: { padding: SIZES.padding, backgroundColor: COLORS.surface, margin: SIZES.margin, borderRadius: SIZES.radius, ...SHADOWS.light, }, contactText: { ...FONTS.body, color: COLORS.text, marginBottom: SIZES.base, }, bookButton: { backgroundColor: COLORS.primary, borderRadius: SIZES.radius, padding: SIZES.padding, alignItems: 'center', margin: SIZES.margin, ...SHADOWS.medium, cursor: 'pointer', }, bookButtonPressed: { opacity: 0.9, }, bookButtonText: { ...FONTS.h3, color: COLORS.background, fontWeight: 'bold', }, tabsContainer: { flexDirection: 'row', marginHorizontal: SIZES.margin, marginBottom: SIZES.margin, backgroundColor: COLORS.surface, borderRadius: SIZES.radius, padding: SIZES.base, ...SHADOWS.light, }, tab: { flex: 1, paddingVertical: SIZES.base, alignItems: 'center', borderRadius: SIZES.base, cursor: 'pointer', }, tabPressed: { opacity: 0.7, }, activeTab: { backgroundColor: COLORS.primary, }, tabText: { ...FONTS.body, color: COLORS.textSecondary, }, activeTabText: { color: COLORS.background, fontWeight: 'bold', }, tabContent: { marginHorizontal: SIZES.margin, marginBottom: SIZES.margin * 2, }, noReviewsText: { ...FONTS.body, color: COLORS.textSecondary, textAlign: 'center', paddingVertical: SIZES.padding, }, availabilityContainer: { backgroundColor: COLORS.surface, borderRadius: SIZES.radius, padding: SIZES.padding, ...SHADOWS.light, }, dayRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: SIZES.base, borderBottomWidth: 1, borderBottomColor: COLORS.border, }, dayText: { ...FONTS.body, color: COLORS.text, flex: 1, }, timeSlots: { flex: 2, flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'flex-end', }, timeSlot: { ...FONTS.caption, color: COLORS.primary, backgroundColor: COLORS.background, paddingHorizontal: SIZES.base, paddingVertical: SIZES.base / 2, borderRadius: SIZES.base / 2, marginLeft: SIZES.base / 2, marginBottom: SIZES.base / 2, }, closedText: { ...FONTS.caption, color: COLORS.textSecondary, fontStyle: 'italic', }, }); export default BarberDetailScreen;