diff --git a/VERSION b/VERSION index d917d3e..845639e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.2 +0.1.4 diff --git a/app/(report)/negativePoints.tsx b/app/(report)/negativePoints.tsx index eb1f651..c678e33 100644 --- a/app/(report)/negativePoints.tsx +++ b/app/(report)/negativePoints.tsx @@ -1,17 +1,44 @@ import { Container } from '@/components/general/container'; import { Header } from '@/components/general/header'; -import { View } from 'react-native'; +import { CardItemFeedback } from '@/components/report/CardItemFeedback'; +import { CardListSkeleton } from '@/components/report/cardListSkeleton'; +import { getReport } from '@/services/reports'; +import { AIReportDetail } from '@/types/Report'; +import { useLocalSearchParams } from 'expo-router'; +import { useEffect, useState } from 'react'; +import { ScrollView, View } from 'react-native'; export default function NegativePoints() { + const { report_id } = useLocalSearchParams<{ report_id: string }>(); + const [report, setReport] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + if (!report_id) return; + getReport(report_id) + .then(setReport) + .finally(() => setLoading(false)); + }, [report_id]); + return ( - -
- + +
+ + {loading ? ( + + ) : report ? ( + {}} + /> + ) : null} + + ); } diff --git a/app/(report)/positivePoints.tsx b/app/(report)/positivePoints.tsx index fb283fd..dfe0c01 100644 --- a/app/(report)/positivePoints.tsx +++ b/app/(report)/positivePoints.tsx @@ -1,17 +1,44 @@ import { Container } from '@/components/general/container'; import { Header } from '@/components/general/header'; -import { View } from 'react-native'; +import { CardItemFeedback } from '@/components/report/CardItemFeedback'; +import { CardListSkeleton } from '@/components/report/cardListSkeleton'; +import { getReport } from '@/services/reports'; +import { AIReportDetail } from '@/types/Report'; +import { useLocalSearchParams } from 'expo-router'; +import { useEffect, useState } from 'react'; +import { ScrollView, View } from 'react-native'; export default function PositivePoints() { + const { report_id } = useLocalSearchParams<{ report_id: string }>(); + const [report, setReport] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + if (!report_id) return; + getReport(report_id) + .then(setReport) + .finally(() => setLoading(false)); + }, [report_id]); + return ( - -
- + +
+ + {loading ? ( + + ) : report ? ( + {}} + /> + ) : null} + + ); } diff --git a/app/(report)/recomendations.tsx b/app/(report)/recomendations.tsx index 8e63e8a..bfb33bb 100644 --- a/app/(report)/recomendations.tsx +++ b/app/(report)/recomendations.tsx @@ -1,13 +1,44 @@ import { Container } from '@/components/general/container'; import { Header } from '@/components/general/header'; -import { View } from 'react-native'; +import { CardItemFeedback } from '@/components/report/CardItemFeedback'; +import { CardListSkeleton } from '@/components/report/cardListSkeleton'; +import { getReport } from '@/services/reports'; +import { AIReportDetail } from '@/types/Report'; +import { useLocalSearchParams } from 'expo-router'; +import { useEffect, useState } from 'react'; +import { ScrollView, View } from 'react-native'; export default function Recomendations() { + const { report_id } = useLocalSearchParams<{ report_id: string }>(); + const [report, setReport] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + if (!report_id) return; + getReport(report_id) + .then(setReport) + .finally(() => setLoading(false)); + }, [report_id]); + return ( - +
- + + {loading ? ( + + ) : report ? ( + {}} + /> + ) : null} + + ); } diff --git a/app/(report)/report.tsx b/app/(report)/report.tsx index da083cc..d67c847 100644 --- a/app/(report)/report.tsx +++ b/app/(report)/report.tsx @@ -1,24 +1,66 @@ import { Container } from '@/components/general/container'; +import GeneralButton from '@/components/general/generalButton'; import { Header } from '@/components/general/header'; import { CardList } from '@/components/report/CardList'; import { CardListSkeleton } from '@/components/report/cardListSkeleton'; -import { ChatButton } from '@/components/report/chatButton'; -import { useState } from 'react'; -import { View } from 'react-native'; +import { generateReport, getReportsByEnterprise } from '@/services/reports'; +import { AIReportSummary } from '@/types/Report'; +import { useEffect, useState } from 'react'; +import { Text, View } from 'react-native'; + +const ENTERPRISE_ID = 'caa68f64-b68e-4327-90f0-264ca1bb73e2'; export default function Report() { - const [loading, setLoading] = useState(false); + const [report, setReport] = useState(null); + const [loading, setLoading] = useState(true); + const [generating, setGenerating] = useState(false); + + useEffect(() => { + fetchLatestReport(); + }, []); + + const fetchLatestReport = async () => { + try { + setLoading(true); + const reports = await getReportsByEnterprise(ENTERPRISE_ID); + if (reports.length > 0) { + setReport(reports[reports.length - 1]); + } + } finally { + setLoading(false); + } + }; - const handlePress = () => { - setLoading; //to do + const handleGenerate = async () => { + try { + setGenerating(true); + const newReport = await generateReport(ENTERPRISE_ID); + setReport(newReport); + } finally { + setGenerating(false); + } }; return (
- - {loading ? : } + {loading ? ( + + ) : report ? ( + + ) : ( + + + Nenhum relatório gerado ainda. Gere o primeiro relatório do seu negócio. + + + + )} ); diff --git a/components/report/CardItem.tsx b/components/report/CardItem.tsx index be948ae..a4a49c0 100644 --- a/components/report/CardItem.tsx +++ b/components/report/CardItem.tsx @@ -48,8 +48,41 @@ export const CardItem = ({ icon, typeCard, topics, handlePress }: Props) => { key={item.id} className="flex-row items-center justify-start gap-4 mb-1" > - - {item.text} + + + {typeCard === 'positive' && + <> + Pontos positivos + + + } + {typeCard === 'negative' && + <> + Pontos negativos + + + } + {typeCard === 'recomendation' && + <> + Recomendações + + + } + + + {topics.map(item=> ( + + + {item.text} + + ))} + + Ver Sugestões + + ))} void +} + +export const CardItemFeedback = ({ + icon, + typeCard, + text, + chages, + automaticChanges, + handlePress, +}: Props)=> { + + const backgroundColor = { + positive: 'bg-green-500/30', + negative: 'bg-red-500/30', + recomendation: 'bg-blue-500/30', + } + + const title = { + positive: 'Pontos positivos', + negative: 'Pontos negativos', + recomendation: 'Recomendações', + } + + return( + + + + + + {title[typeCard]} + + + + + + {text} + + {automaticChanges && + + + + {chages} + + + + + Aplicar mudanças + + + + } + + ) +} \ No newline at end of file diff --git a/components/report/CardList.tsx b/components/report/CardList.tsx index e6d7a59..5d18dac 100644 --- a/components/report/CardList.tsx +++ b/components/report/CardList.tsx @@ -1,49 +1,43 @@ -import { router } from 'expo-router'; -import { View } from 'react-native'; -import { CardItem } from './CardItem'; +import { AIReportSummary } from '@/types/Report' +import { router } from 'expo-router' +import { View } from 'react-native' +import { CardItem } from './CardItem' + +type Props = { + report: AIReportSummary +} + +export const CardList = ({ report }: Props) => { + const handlePressPositive = () => { + router.navigate({ pathname: '/positivePoints' as any, params: { report_id: report.id_relatorio } }) + } + const handlePressNegative = () => { + router.navigate({ pathname: '/negativePoints' as any, params: { report_id: report.id_relatorio } }) + } + const handlePressRecomendation = () => { + router.navigate({ pathname: '/recomendations' as any, params: { report_id: report.id_relatorio } }) + } -export const CardList = () => { - const handlePresPositive = () => { - router.navigate('/(report)/positivePoints'); - }; - const handlePresNegative = () => { - router.navigate('/(report)/negativePoints'); - }; - const handlePresRecomendation = () => { - router.navigate('/(report)/recomendations'); - }; return ( - ); -}; + ) +} diff --git a/components/report/NegativeFeedbackList.tsx b/components/report/NegativeFeedbackList.tsx new file mode 100644 index 0000000..ec1ce38 --- /dev/null +++ b/components/report/NegativeFeedbackList.tsx @@ -0,0 +1,43 @@ +import { FeedbackItem } from '@/types/FeedbackItem' +import { View } from 'react-native' +import { CardItemFeedback } from './CardItemFeedback' + +export const NegativeFeedbackList = ({ handlePress }: { handlePress: () => void }) => { + + const feedbacks: FeedbackItem[] = [ + { + id: '1', + text: 'O tempo médio de entrega aumentou para 52 minutos neste mês, impactando negativamente a experiência dos clientes.', + changes: 'Vou sugerir ajustes na logística de entregas para reduzir o tempo.', + automaticChanges: true, + }, + { + id: '2', + text: 'Houve um aumento de 25% nas avaliações negativas relacionadas à temperatura dos alimentos.', + changes: 'Vou recomendar melhorias na embalagem térmica.', + automaticChanges: true, + }, + { + id: '3', + text: 'A taxa de cancelamento de pedidos subiu para 12%, acima da média esperada.', + changes: '', + automaticChanges: false, + }, + ] + + return ( + + {feedbacks.map(item => ( + + ))} + + ) +} \ No newline at end of file diff --git a/components/report/PositiveFeedbackList.tsx b/components/report/PositiveFeedbackList.tsx new file mode 100644 index 0000000..c0a6ade --- /dev/null +++ b/components/report/PositiveFeedbackList.tsx @@ -0,0 +1,41 @@ +import { FeedbackItem } from '@/types/FeedbackItem' +import { View } from 'react-native' +import { CardItemFeedback } from './CardItemFeedback' +export const PositiveFeedbackList = ({ handlePress }: { handlePress: () => void }) => { + + const feedbacks: FeedbackItem[] = [ + { + id: '1', + text: 'Seu estabelecimento recebeu avaliações positivas com média de 4.8 estrelas este mês.', + changes: '', + automaticChanges: false, + }, + { + id: '2', + text: 'A sopa de feijão foi o prato mais pedido do seu estabelecimento, somando 145 pedidos neste mês. Isso representa um aumento de 18% em comparação ao mês anterior.', + changes: 'Vou destacar a sopa como prato principal no seu cardápio.', + automaticChanges: true, + }, + { + id: '3', + text: 'Seu tempo médio de entrega reduziu para 28 minutos, melhorando a experiência dos clientes.', + changes: 'Vou destacar sua agilidade como diferencial no app.', + automaticChanges: true, + }, + ] + return ( + + {feedbacks.map(item => ( + + ))} + + ) +} \ No newline at end of file diff --git a/components/report/RecommendationFeedbackList.tsx b/components/report/RecommendationFeedbackList.tsx new file mode 100644 index 0000000..0fd920d --- /dev/null +++ b/components/report/RecommendationFeedbackList.tsx @@ -0,0 +1,43 @@ +import { FeedbackItem } from '@/types/FeedbackItem' +import { View } from 'react-native' +import { CardItemFeedback } from './CardItemFeedback' + +export const RecommendationFeedbackList = ({ handlePress }: { handlePress: () => void }) => { + + const feedbacks: FeedbackItem[] = [ + { + id: '1', + text: 'Adicionar combos promocionais pode aumentar o ticket médio dos pedidos.', + changes: 'Vou criar sugestões de combos com seus pratos mais vendidos.', + automaticChanges: true, + }, + { + id: '2', + text: 'Investir em fotos mais atrativas dos pratos pode aumentar a conversão de pedidos.', + changes: '', + automaticChanges: false, + }, + { + id: '3', + text: 'Expandir o horário de funcionamento pode atrair mais clientes no período da noite.', + changes: 'Vou recomendar horários ideais com base na demanda.', + automaticChanges: true, + }, + ] + + return ( + + {feedbacks.map(item => ( + + ))} + + ) +} \ No newline at end of file diff --git a/constants/api.ts b/constants/api.ts index be19e3d..91a4616 100644 --- a/constants/api.ts +++ b/constants/api.ts @@ -1,2 +1,2 @@ export const API_URL = - process.env.EXPO_PUBLIC_API_URL ?? 'http://localhost:8000'; + process.env.EXPO_PUBLIC_API_URL ?? 'https://mandaca-backend-production.onrender.com'; diff --git a/services/reports.ts b/services/reports.ts new file mode 100644 index 0000000..cffa10f --- /dev/null +++ b/services/reports.ts @@ -0,0 +1,17 @@ +import { API_URL } from '@/constants/api' +import { AIReportDetail, AIReportSummary } from '@/types/Report' + +export const generateReport = async (empresaId: string): Promise => { + const res = await fetch(`${API_URL}/reports/generate/${empresaId}`, { method: 'POST' }) + return res.json() +} + +export const getReportsByEnterprise = async (empresaId: string): Promise => { + const res = await fetch(`${API_URL}/reports/by-enterprise/${empresaId}`) + return res.json() +} + +export const getReport = async (reportId: string): Promise => { + const res = await fetch(`${API_URL}/reports/${reportId}`) + return res.json() +} diff --git a/types/FeedbackItem.ts b/types/FeedbackItem.ts new file mode 100644 index 0000000..924d3db --- /dev/null +++ b/types/FeedbackItem.ts @@ -0,0 +1,6 @@ +export type FeedbackItem = { + id: string + text: string + changes: string + automaticChanges: boolean +} \ No newline at end of file diff --git a/types/Report.ts b/types/Report.ts new file mode 100644 index 0000000..5891303 --- /dev/null +++ b/types/Report.ts @@ -0,0 +1,15 @@ +export type AIReportSummary = { + id_relatorio: string + empresa_id: string + contexto_id: string + pontos_positivos_resumo: string + melhorias_resumo: string + recomendacoes_resumo: string + criado_em: string +} + +export type AIReportDetail = AIReportSummary & { + pontos_positivos_detalhado: string + melhorias_detalhado: string + recomendacoes_detalhado: string +}