Skip to content

Commit de2dee4

Browse files
committed
2 parents 1f65856 + 1bcf4a9 commit de2dee4

3 files changed

Lines changed: 166 additions & 23 deletions

File tree

Lines changed: 125 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,134 @@
1-
import { View, Text, StyleSheet } from 'react-native';
1+
import { useEffect, useState, useCallback } from 'react';
2+
import {
3+
View, Text, FlatList, StyleSheet,
4+
ActivityIndicator, Modal, TouchableOpacity, Alert,
5+
} from 'react-native';
6+
import AsyncStorage from '@react-native-async-storage/async-storage';
7+
import axios from 'axios';
8+
import { BASE_URL, EMPRESTIMOS } from '@constants/endpoints';
9+
import { useAuth } from '@hooks/useAuth';
10+
import { Emprestimo } from 'emprestimo';
11+
import { EmprestimoListItem } from '@components/emprestimos/EmprestimoListItem';
12+
import { EmprestimoCard } from '@components/emprestimos/EmprestimoCard';
13+
14+
const TOKEN_KEY = '@pagaai:token';
15+
16+
async function req(method: 'get' | 'patch' | 'delete', path: string) {
17+
const token = await AsyncStorage.getItem(TOKEN_KEY);
18+
return axios({ method, url: `${BASE_URL}${path}`, headers: { Authorization: `Bearer ${token}` } });
19+
}
220

321
export default function EmprestimosScreen() {
22+
const { user } = useAuth();
23+
const cobrador = user?.nome ?? '';
24+
25+
const [lista, setLista] = useState<Emprestimo[]>([]);
26+
const [carregando, setCarregando] = useState(true);
27+
const [selecionado, setSelecionado] = useState<Emprestimo | null>(null);
28+
29+
const carregar = useCallback(async () => {
30+
if (!cobrador) return;
31+
setCarregando(true);
32+
try {
33+
const url = `${EMPRESTIMOS}/carteira/${encodeURIComponent(cobrador)}`;
34+
console.log('[Emprestimos] chamando:', url);
35+
const res = await req('get', url);
36+
console.log('[Emprestimos] total:', res.data?.length);
37+
setLista(Array.isArray(res.data) ? res.data : []);
38+
} catch (e: any) {
39+
console.error('[Emprestimos] erro:', e?.response?.status, e?.response?.data ?? e?.message);
40+
} finally {
41+
setCarregando(false);
42+
}
43+
}, [cobrador]);
44+
45+
useEffect(() => { carregar(); }, [carregar]);
46+
47+
async function marcarPago(id: number) {
48+
Alert.alert('Confirmar', 'Marcar como recebido?', [
49+
{ text: 'Cancelar', style: 'cancel' },
50+
{
51+
text: 'Confirmar', onPress: async () => {
52+
try {
53+
await req('patch', `${EMPRESTIMOS}/${id}/pagar/${encodeURIComponent(cobrador)}`);
54+
setSelecionado(null);
55+
carregar();
56+
} catch { Alert.alert('Erro', 'Não foi possível marcar como pago.'); }
57+
},
58+
},
59+
]);
60+
}
61+
62+
async function deletar(id: number) {
63+
Alert.alert('Excluir', 'Deseja excluir este empréstimo?', [
64+
{ text: 'Cancelar', style: 'cancel' },
65+
{
66+
text: 'Excluir', style: 'destructive', onPress: async () => {
67+
try {
68+
await req('delete', `${EMPRESTIMOS}/${id}/${encodeURIComponent(cobrador)}`);
69+
setSelecionado(null);
70+
carregar();
71+
} catch { Alert.alert('Erro', 'Não foi possível excluir.'); }
72+
},
73+
},
74+
]);
75+
}
76+
77+
if (carregando) {
78+
return <View style={s.center}><ActivityIndicator size="large" color="#7C3AED" /></View>;
79+
}
80+
481
return (
5-
<View style={s.container}>
6-
<Text style={s.icon}>💳</Text>
7-
<Text style={s.titulo}>Empréstimos</Text>
8-
<Text style={s.sub}>Tela em desenvolvimento</Text>
82+
<View style={s.page}>
83+
<View style={s.header}>
84+
<Text style={s.titulo}>Empréstimos</Text>
85+
<Text style={s.sub}>{lista.length} registro{lista.length !== 1 ? 's' : ''}</Text>
86+
</View>
87+
88+
{lista.length === 0 ? (
89+
<View style={s.center}>
90+
<Text style={s.vazio}>Nenhum empréstimo encontrado.</Text>
91+
</View>
92+
) : (
93+
<FlatList
94+
data={lista}
95+
keyExtractor={(e) => String(e.id)}
96+
renderItem={({ item }) => (
97+
<EmprestimoListItem
98+
emprestimo={item}
99+
onPress={(id) => setSelecionado(lista.find((e) => e.id === id) ?? null)}
100+
/>
101+
)}
102+
contentContainerStyle={{ paddingBottom: 32 }}
103+
/>
104+
)}
105+
106+
<Modal visible={!!selecionado} animationType="slide" onRequestClose={() => setSelecionado(null)}>
107+
<View style={s.modalPage}>
108+
<TouchableOpacity style={s.fechar} onPress={() => setSelecionado(null)}>
109+
<Text style={s.fecharText}>← Voltar</Text>
110+
</TouchableOpacity>
111+
{selecionado && (
112+
<EmprestimoCard
113+
emprestimo={selecionado}
114+
onPagar={marcarPago}
115+
onDeletar={deletar}
116+
/>
117+
)}
118+
</View>
119+
</Modal>
9120
</View>
10121
);
11122
}
12123

13124
const s = StyleSheet.create({
14-
container: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: '#F5F3FF' },
15-
icon: { fontSize: 48, marginBottom: 12 },
16-
titulo: { fontSize: 22, fontWeight: '700', color: '#1F2937' },
17-
sub: { fontSize: 14, color: '#6B7280', marginTop: 6 },
125+
page: { flex: 1, backgroundColor: '#F5F3FF' },
126+
center: { flex: 1, alignItems: 'center', justifyContent: 'center' },
127+
header: { padding: 20, paddingBottom: 12 },
128+
titulo: { fontSize: 28, fontWeight: '700', color: '#1F2937' },
129+
sub: { fontSize: 13, color: '#6B7280', marginTop: 2 },
130+
vazio: { fontSize: 15, color: '#9CA3AF' },
131+
modalPage: { flex: 1, backgroundColor: '#F5F3FF', padding: 16 },
132+
fechar: { paddingVertical: 12, marginBottom: 8 },
133+
fecharText: { fontSize: 15, color: '#7C3AED', fontWeight: '600' },
18134
});

src/mobile/app/(tabs)/index.tsx

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,25 @@ import React, { useEffect, useState } from 'react';
22
import { View, Text, ScrollView, StyleSheet, TouchableOpacity, ActivityIndicator } from 'react-native';
33
import { useRouter } from 'expo-router';
44
import { useAuth } from '@hooks/useAuth';
5+
<<<<<<< HEAD
56
import api from '@services/api';
67
import { CLIENTES, EMPRESTIMOS, REPORT } from '@constants/endpoints';
78
import { Emprestimo, fmt } from '@types/emprestimo';
9+
=======
10+
import axios from 'axios';
11+
import AsyncStorage from '@react-native-async-storage/async-storage';
12+
import { BASE_URL, CLIENTES, EMPRESTIMOS } from '@constants/endpoints';
13+
import { Emprestimo, fmt } from '../../types/emprestimo';
14+
15+
const TOKEN_KEY = '@pagaai:token';
16+
17+
async function get(path: string) {
18+
const token = await AsyncStorage.getItem(TOKEN_KEY);
19+
return axios.get(`${BASE_URL}${path}`, {
20+
headers: { Authorization: `Bearer ${token}` },
21+
});
22+
}
23+
>>>>>>> 1bcf4a97304bfeaca1e3049333962bb7330653e5
824

925
interface Stats {
1026
clientes: number;
@@ -49,15 +65,20 @@ export default function DashboardScreen() {
4965
async function carregar() {
5066
try {
5167
const cobrador = user?.nome ?? '';
52-
const [resClientes, resCarteira, resLucro] = await Promise.all([
53-
api.get(CLIENTES),
54-
api.get(`${EMPRESTIMOS}/carteira/${encodeURIComponent(cobrador)}`),
55-
api.get(`${REPORT}/relatorio-lucro/${encodeURIComponent(cobrador)}`),
56-
]);
5768

58-
const clientes: unknown[] = Array.isArray(resClientes.data) ? resClientes.data : [];
59-
const lista: Emprestimo[] = Array.isArray(resCarteira.data) ? resCarteira.data : [];
60-
const lucro = resLucro.data;
69+
const resClientes = await get(CLIENTES).catch((e) => {
70+
console.error('[Dashboard] ERRO clientes:', e?.response?.status, e?.message); return null;
71+
});
72+
const resCarteira = await get(`${EMPRESTIMOS}/carteira/${encodeURIComponent(cobrador)}`).catch((e) => {
73+
console.error('[Dashboard] ERRO carteira:', e?.response?.status, e?.message); return null;
74+
});
75+
const resLucro = await get(`${EMPRESTIMOS}/relatorio-lucro/${encodeURIComponent(cobrador)}`).catch((e) => {
76+
console.error('[Dashboard] ERRO lucro:', e?.response?.status, e?.message); return null;
77+
});
78+
79+
const clientes: unknown[] = Array.isArray(resClientes?.data) ? resClientes.data : [];
80+
const lista: Emprestimo[] = Array.isArray(resCarteira?.data) ? resCarteira.data : [];
81+
const lucro = resLucro?.data;
6182

6283
const emDia = lista.filter((e) => calcularStatus(e) === 'emDia');
6384
const atrasados = lista.filter((e) => calcularStatus(e) === 'atraso');
@@ -76,7 +97,8 @@ export default function DashboardScreen() {
7697
aReceber: lucro?.resumoGeral?.recebimentoTotalGeral ?? 0,
7798
lucro: lucro?.resumoGeral?.lucroTotalProjetado ?? 0,
7899
});
79-
} catch {
100+
} catch (error: any) {
101+
console.error('[Dashboard] ERRO:', error?.response?.status, error?.response?.data ?? error?.message);
80102
setStats({ clientes: 0, emprestimos: 0, emDia: 0, atraso: 0, investido: 0, aReceber: 0, lucro: 0 });
81103
} finally {
82104
setCarregando(false);
@@ -136,8 +158,13 @@ export default function DashboardScreen() {
136158
<ScrollView style={s.page} contentContainerStyle={s.content} showsVerticalScrollIndicator={false}>
137159
{/* Header */}
138160
<View style={s.header}>
161+
<<<<<<< HEAD
139162
<Text style={s.saudacao}>{saudacao()}, {nome} 👋</Text>
140163
<Text style={s.titulo}>Painel</Text>
164+
=======
165+
<Text style={s.titulo}>Painel</Text>
166+
<Text style={s.saudacao}>{saudacao()}, {nome} 👋</Text>
167+
>>>>>>> 1bcf4a97304bfeaca1e3049333962bb7330653e5
141168
</View>
142169

143170
{/* Cards de contagem */}

src/mobile/constants/endpoints.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
export const BASE_URL = 'https://gateway-hxc8cshmfsd9cwdt.eastus-01.azurewebsites.net';
44
export const DEV_BASE_URL = 'http://localhost:5046';
55

6-
export const USUARIOS = '/api/usuarios';
7-
export const CLIENTES = '/api/clientes';
8-
export const EMPRESTIMOS = '/api/emprestimos';
9-
export const NOTIFICACOES = '/api/notificacoes';
10-
export const REPORT = '/api/report';
6+
export const USUARIOS = '/backend/Usuarios';
7+
export const CLIENTES = '/backend/Clientes';
8+
export const EMPRESTIMOS = '/backend/Emprestimos';
9+
export const NOTIFICACOES = '/backend/Notificacoes';
10+
export const REPORT = '/backend/Report';

0 commit comments

Comments
 (0)