Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions app/(mybusiness)/reviews.tsx
Original file line number Diff line number Diff line change
@@ -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<ReviewFilterType>('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'
Expand All @@ -33,7 +49,15 @@ export default function Reviews() {
onFilterChange={handleFilterChange}
/>

{filteredReviews.length > 0 ? (
{loading ? (
<View className="items-center justify-center py-12">
<ActivityIndicator size="large" />
</View>
) : error ? (
<View className="items-center justify-center py-12">
<Text className="text-dark text-center text-sm">{error}</Text>
</View>
) : filteredReviews.length > 0 ? (
<View className="gap-4">
{filteredReviews.map((review) => (
<ReviewCard
Expand Down
59 changes: 0 additions & 59 deletions components/MyBusiness/reviewCard/mock.ts

This file was deleted.

28 changes: 14 additions & 14 deletions components/MyBusiness/reviewsFilter/main.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from 'react';
import { Pressable, View, Text, StyleSheet } from 'react-native';
import { Pressable, StyleSheet, Text, View } from 'react-native';

export type ReviewFilterType = 'todos' | 'elogios' | 'dicas' | 'duvidas';
export type ReviewFilterType = 'todos' | 'positiva' | 'negativa' | 'neutra' | 'sugestao' | 'duvida';

interface ReviewsFilterNavProps {
onFilterChange: (filter: ReviewFilterType) => void;
Expand All @@ -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 = ({
Expand All @@ -28,16 +30,15 @@ export const ReviewsFilterNav = ({
};

return (
<View className="flex-row gap-3">
<View className="flex-row flex-wrap justify-center items-center gap-3 px-4 py-4">
{FILTER_OPTIONS.map((filter) => (
<Pressable
key={filter.id}
onPress={() => 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
Expand All @@ -46,9 +47,8 @@ export const ReviewsFilterNav = ({
]}
>
<Text
className={`text-base font-bold leading-6 ${
activeFilter === filter.id ? 'text-light' : 'text-dark'
}`}
className={`text-base font-bold leading-6 ${activeFilter === filter.id ? 'text-light' : 'text-dark'
}`}
>
{filter.label}
</Text>
Expand Down
34 changes: 22 additions & 12 deletions constants/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
},
};
61 changes: 61 additions & 0 deletions hooks/useAssessments.ts
Original file line number Diff line number Diff line change
@@ -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<void>;
}

export const useAssessments = (enterpriseId: string): UseAssessmentsResult => {
const [assessments, setAssessments] = useState<Assessment[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(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,
};
};
67 changes: 67 additions & 0 deletions services/assessmentService.ts
Original file line number Diff line number Diff line change
@@ -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<Assessment[]> => {
const response = await axios.get(
`${API_URL}/assessments/by-enterprise/${enterpriseId}`
);
return response.data;
};

export const getAllAssessments = async (): Promise<Assessment[]> => {
const response = await axios.get(`${API_URL}/assessments`);
return response.data;
};

export const getAssessmentById = async (
assessmentId: string
): Promise<Assessment> => {
const response = await axios.get(`${API_URL}/assessments/${assessmentId}`);
return response.data;
};

export const createAssessment = async (
texto: string,
usuarioId: string,
empresaId: string
): Promise<Assessment> => {
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<Assessment> => {
const response = await axios.put(
`${API_URL}/assessments/${assessmentId}`,
data
);
return response.data;
};

export const deleteAssessment = async (
assessmentId: string
): Promise<void> => {
await axios.delete(`${API_URL}/assessments/${assessmentId}`);
};
18 changes: 18 additions & 0 deletions services/userService.ts
Original file line number Diff line number Diff line change
@@ -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<User | null> => {
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;
}
};
Loading
Loading