diff --git a/app/(mybusiness)/reviews.tsx b/app/(mybusiness)/reviews.tsx index 4760852..851472c 100644 --- a/app/(mybusiness)/reviews.tsx +++ b/app/(mybusiness)/reviews.tsx @@ -1,19 +1,35 @@ -import { useState } from 'react'; import { Container } from '@/components/general/container'; import { Header } from '@/components/general/header'; +import { ReviewCard } from '@/components/MyBusiness/reviewCard/main'; import { ReviewsFilterNav, type ReviewFilterType, } from '@/components/MyBusiness/reviewsFilter/main'; -import { ReviewCard } from '@/components/MyBusiness/reviewCard/main'; -import { MOCK_REVIEWS } from '@/components/MyBusiness/reviewCard/mock'; -import { View, Text } from 'react-native'; +import { useAssessments } from '@/hooks/useAssessments'; +import { Assessment } from '@/services/assessmentService'; +import { ReviewSentiment } from '@/types'; +import { useState } from 'react'; +import { ActivityIndicator, Text, View } from 'react-native'; + +const ENTERPRISE_ID = 'caa68f64-b68e-4327-90f0-264ca1bb73e2'; + +interface ReviewItem { + id: string; + name: string; + sentiment: ReviewSentiment; + comment: string; +} export default function Reviews() { const [activeFilter, setActiveFilter] = useState('todos'); + const { assessments, loading, error } = useAssessments(ENTERPRISE_ID); - // requisicao do backend para pegar as reviews, por enquanto usando mock - const reviews = MOCK_REVIEWS; + const reviews: ReviewItem[] = assessments.map((assessment: Assessment) => ({ + id: assessment.id_avaliacao, + name: assessment.usuario_nome || 'Anônimo', + sentiment: assessment.tipo_avaliacao, + comment: assessment.texto, + })); const filteredReviews = activeFilter === 'todos' @@ -33,7 +49,15 @@ export default function Reviews() { onFilterChange={handleFilterChange} /> - {filteredReviews.length > 0 ? ( + {loading ? ( + + + + ) : error ? ( + + {error} + + ) : filteredReviews.length > 0 ? ( {filteredReviews.map((review) => ( void; @@ -10,9 +10,11 @@ interface ReviewsFilterNavProps { const FILTER_OPTIONS: { id: ReviewFilterType; label: string }[] = [ { id: 'todos', label: 'Todos' }, - { id: 'elogios', label: 'Elogios' }, - { id: 'dicas', label: 'Dicas' }, - { id: 'duvidas', label: 'Dúvidas' }, + { id: 'positiva', label: 'Positiva' }, + { id: 'negativa', label: 'Negativa' }, + { id: 'neutra', label: 'Neutra' }, + { id: 'sugestao', label: 'Sugestão' }, + { id: 'duvida', label: 'Dúvida' }, ]; export const ReviewsFilterNav = ({ @@ -28,16 +30,15 @@ export const ReviewsFilterNav = ({ }; return ( - + {FILTER_OPTIONS.map((filter) => ( handleFilterPress(filter.id)} - className={`flex-1 h-10 rounded-lg justify-center items-center ${ - activeFilter === filter.id - ? 'bg-primary' - : 'bg-light border border-secondary' - }`} + className={`h-10 rounded-lg justify-center items-center px-4 ${activeFilter === filter.id + ? 'bg-primary' + : 'bg-light border border-secondary' + }`} style={[ styles.filterButton, activeFilter === filter.id @@ -46,9 +47,8 @@ export const ReviewsFilterNav = ({ ]} > {filter.label} diff --git a/constants/theme.ts b/constants/theme.ts index 6ac358e..f724be4 100644 --- a/constants/theme.ts +++ b/constants/theme.ts @@ -54,19 +54,29 @@ export const Fonts = Platform.select({ }); export const SENTIMENT_CONFIG = { - elogios: { - label: 'Elogio', - bgColor: '#F4EBE8', - textColor: '#AD3C00', + positiva: { + label: 'Positiva', + bgColor: '#E0F9F0', + textColor: '#00896B', }, - dicas: { - label: 'Dicas', - bgColor: '#F9F3E9', - textColor: '#D19E49', + negativa: { + label: 'Negativa', + bgColor: '#FDE8E8', + textColor: '#C62828', }, - duvidas: { - label: 'Dúvidas', - bgColor: '#DBEAFE', - textColor: '#004BDA', + neutra: { + label: 'Neutra', + bgColor: '#F5F5F5', + textColor: '#424242', + }, + sugestao: { + label: 'Sugestão', + bgColor: '#FFF3E0', + textColor: '#E65100', + }, + duvida: { + label: 'Dúvida', + bgColor: '#E1F5FE', + textColor: '#0D47A1', }, }; diff --git a/hooks/useAssessments.ts b/hooks/useAssessments.ts new file mode 100644 index 0000000..cd44c29 --- /dev/null +++ b/hooks/useAssessments.ts @@ -0,0 +1,61 @@ +import { Assessment, getAssessmentsByEnterprise } from '@/services/assessmentService'; +import { getUserById } from '@/services/userService'; +import { useFocusEffect } from '@react-navigation/native'; +import { useCallback, useState } from 'react'; + +interface UseAssessmentsResult { + assessments: Assessment[]; + loading: boolean; + error: string | null; + refetch: () => Promise; +} + +export const useAssessments = (enterpriseId: string): UseAssessmentsResult => { + const [assessments, setAssessments] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const enrichAssessmentsWithUserNames = async (data: Assessment[]) => { + const enriched = await Promise.all( + data.map(async (assessment) => { + if (!assessment.usuario_nome) { + const user = await getUserById(assessment.usuario_id); + return { + ...assessment, + usuario_nome: user?.nome || 'Anônimo', + }; + } + return assessment; + }) + ); + return enriched; + }; + + const loadAssessments = useCallback(async () => { + try { + setLoading(true); + setError(null); + const data = await getAssessmentsByEnterprise(enterpriseId); + const enriched = await enrichAssessmentsWithUserNames(data); + setAssessments(enriched); + } catch (err) { + console.error('Erro ao carregar avaliações:', err); + setError('Não foi possível carregar as avaliações'); + } finally { + setLoading(false); + } + }, [enterpriseId]); + + useFocusEffect( + useCallback(() => { + loadAssessments(); + }, [loadAssessments]) + ); + + return { + assessments, + loading, + error, + refetch: loadAssessments, + }; +}; diff --git a/services/assessmentService.ts b/services/assessmentService.ts new file mode 100644 index 0000000..943dfe3 --- /dev/null +++ b/services/assessmentService.ts @@ -0,0 +1,67 @@ +import { API_URL } from '@/constants/api'; +import { ReviewSentiment } from '@/types'; +import axios from 'axios'; + +export interface Assessment { + id_avaliacao: string; + texto: string; + tipo_avaliacao: ReviewSentiment; + usuario_id: string; + usuario_nome?: string; + empresa_id: string; +} + +export const getAssessmentsByEnterprise = async ( + enterpriseId: string +): Promise => { + const response = await axios.get( + `${API_URL}/assessments/by-enterprise/${enterpriseId}` + ); + return response.data; +}; + +export const getAllAssessments = async (): Promise => { + const response = await axios.get(`${API_URL}/assessments`); + return response.data; +}; + +export const getAssessmentById = async ( + assessmentId: string +): Promise => { + const response = await axios.get(`${API_URL}/assessments/${assessmentId}`); + return response.data; +}; + +export const createAssessment = async ( + texto: string, + usuarioId: string, + empresaId: string +): Promise => { + const response = await axios.post(`${API_URL}/assessments`, { + texto, + usuario_id: usuarioId, + empresa_id: empresaId, + }); + return response.data; +}; + +export const updateAssessment = async ( + assessmentId: string, + data: Partial<{ + texto: string; + usuario_id: string; + empresa_id: string; + }> +): Promise => { + const response = await axios.put( + `${API_URL}/assessments/${assessmentId}`, + data + ); + return response.data; +}; + +export const deleteAssessment = async ( + assessmentId: string +): Promise => { + await axios.delete(`${API_URL}/assessments/${assessmentId}`); +}; diff --git a/services/userService.ts b/services/userService.ts new file mode 100644 index 0000000..8990d97 --- /dev/null +++ b/services/userService.ts @@ -0,0 +1,18 @@ +import { API_URL } from '@/constants/api'; +import axios from 'axios'; + +export interface User { + id_usuario: string; + nome: string; + email: string; +} + +export const getUserById = async (userId: string): Promise => { + try { + const response = await axios.get(`${API_URL}/users/${userId}`); + return response.data; + } catch (error) { + console.error(`Erro ao buscar usuário ${userId}:`, error); + return null; + } +}; diff --git a/types/assessment.ts b/types/assessment.ts new file mode 100644 index 0000000..d558d81 --- /dev/null +++ b/types/assessment.ts @@ -0,0 +1,44 @@ +import { ReviewSentiment } from './index'; + +export interface AssessmentDTO { + id_avaliacao: string; + texto: string; + tipo_avaliacao: ReviewSentiment; + usuario_id: string; + empresa_id: string; +} + +export interface UserDTO { + id_usuario: string; + nome: string; + email: string; +} + +export interface EnterpriseDTO { + id_empresa: string; + nome: string; +} + +/** + * View enriched de Assessment com dados de usuário e empresa + * Útil quando backend retorna dados relacionados + */ +export interface AssessmentEnrichedDTO extends AssessmentDTO { + usuario?: UserDTO; + empresa?: EnterpriseDTO; +} + +/** + * Estatísticas de avaliações por tipo + * Possível endpoint futuro: GET /assessments/stats/enterprise/{id} + */ +export interface AssessmentStatsDTO { + total: number; + positiva: number; + negativa: number; + neutra: number; + sugestao: number; + duvida: number; + avgSentiment?: number; // -1 a 1 ou percentual + recentCount: number; // últimos 7 dias +} diff --git a/types/index.ts b/types/index.ts index ed5504d..6a1526a 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1 +1 @@ -export type ReviewSentiment = 'elogios' | 'dicas' | 'duvidas'; +export type ReviewSentiment = 'positiva' | 'negativa' | 'neutra' | 'sugestao' | 'duvida';