From 8305abb235bae5e8ebb5cd120c41e1735c4ba7b6 Mon Sep 17 00:00:00 2001 From: Ronaldo Ribeiro Date: Fri, 24 Apr 2026 20:12:59 -0300 Subject: [PATCH 1/5] Scrum-56 fix: removi os dados de mock --- components/MyBusiness/reviewCard/mock.ts | 59 ------------------------ 1 file changed, 59 deletions(-) delete mode 100644 components/MyBusiness/reviewCard/mock.ts diff --git a/components/MyBusiness/reviewCard/mock.ts b/components/MyBusiness/reviewCard/mock.ts deleted file mode 100644 index ac058c4..0000000 --- a/components/MyBusiness/reviewCard/mock.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { ReviewSentiment } from '../../../types'; - -export interface Review { - id: number; - name: string; - sentiment: ReviewSentiment; - comment: string; -} - -export const MOCK_REVIEWS: Review[] = [ - { - id: 1, - name: 'Maria da Silva Santos', - sentiment: 'elogios', - comment: - 'Adorei o atendimento! Comida fresca, bem temperada e equipe muito atenciosa. Voltarei com certeza!', - }, - { - id: 2, - name: 'João Oliveira', - sentiment: 'dicas', - comment: - 'Muito bom! Só sugiro aumentar um pouco a quantidade de tempero no arroz. Mas no geral, recomendo!', - }, - { - id: 3, - name: 'Ana Costa Ribeiro', - sentiment: 'duvidas', - comment: - 'Qual é a procedência das carnes? Vocês usam fornecedores locais? Gostaria de saber mais sobre isso.', - }, - { - id: 4, - name: 'Carlos Mendes', - sentiment: 'elogios', - comment: - 'Excelente culinária nordestina! Ambiente aconchegante e preço justo. Recomendo para todos os amigos!', - }, - { - id: 5, - name: 'Fernanda Gomes', - sentiment: 'dicas', - comment: - 'Pensei que teria mais opções vegetarianas. Mas os drinks são incríveis! Voltarei para experimentar mais.', - }, - { - id: 6, - name: 'Roberto Alves', - sentiment: 'duvidas', - comment: 'Fazem delivery? Qual é o tempo de entrega para a região central?', - }, - { - id: 7, - name: 'Lucia Martins', - sentiment: 'elogios', - comment: - 'Melhor comida que já comi! Parabéns à equipe. Voltei 3 vezes em um mês, isso é tudo que preciso falar.', - }, -]; From 8cabb99ea6a0d10157b292edb932affa615bcc6c Mon Sep 17 00:00:00 2001 From: Ronaldo Ribeiro Date: Fri, 24 Apr 2026 20:18:37 -0300 Subject: [PATCH 2/5] =?UTF-8?q?Scrum-56=20feat:=20integra=C3=A7=C3=A3o=20c?= =?UTF-8?q?om=20a=20api=20e=20ajustes=20menores=20de=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(mybusiness)/reviews.tsx | 38 ++++++++++++++++---- components/MyBusiness/reviewsFilter/main.tsx | 28 +++++++-------- components/report/CardList.tsx | 22 ++++++------ 3 files changed, 56 insertions(+), 32 deletions(-) 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/components/report/CardList.tsx b/components/report/CardList.tsx index 7a2db84..b55d3e2 100644 --- a/components/report/CardList.tsx +++ b/components/report/CardList.tsx @@ -2,32 +2,32 @@ import { router } from 'expo-router' import { View } from 'react-native' import { CardItem } from './CardItem' -export const CardList = ()=> { - const handlePresPositive = ()=> { +export const CardList = () => { + const handlePresPositive = () => { router.navigate('/(report)/positivePoints') } - const handlePresNegative = ()=> { + const handlePresNegative = () => { router.navigate('/(report)/negativePoints') } - const handlePresRecomendation = ()=> { + const handlePresRecomendation = () => { router.navigate('/(report)/recomendations') } - return( + return ( { Date: Fri, 24 Apr 2026 20:19:46 -0300 Subject: [PATCH 3/5] Scrum-56 feat: assessment e user services --- services/assessmentService.ts | 67 +++++++++++++++++++++++++++++++++++ services/userService.ts | 18 ++++++++++ 2 files changed, 85 insertions(+) create mode 100644 services/assessmentService.ts create mode 100644 services/userService.ts 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; + } +}; From 9590b25ca9021900e87fe17030985ff506f9fb3a Mon Sep 17 00:00:00 2001 From: Ronaldo Ribeiro Date: Fri, 24 Apr 2026 20:20:23 -0300 Subject: [PATCH 4/5] Scrum-56 feat: assessments & sentiment types --- hooks/useAssessments.ts | 61 +++++++++++++++++++++++++++++++++++++++++ types/assessment.ts | 44 +++++++++++++++++++++++++++++ types/index.ts | 2 +- 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 hooks/useAssessments.ts create mode 100644 types/assessment.ts 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/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'; From 9f1b26aed2bf002b2afc53ab92eee0a37cc4762e Mon Sep 17 00:00:00 2001 From: Ronaldo Ribeiro Date: Fri, 24 Apr 2026 20:26:53 -0300 Subject: [PATCH 5/5] Scrum-56 feat: ajuste no tema dos sentimentos --- constants/theme.ts | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) 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', }, };