diff --git a/backend/pom.xml b/backend/pom.xml index 6905d3aa..f690d539 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -29,6 +29,8 @@ 21 + 21 + 21 @@ -149,7 +151,7 @@ false 100 - 1.7 + 21 diff --git a/backend/src/main/java/br/com/servicemaker/controller/AgendaController.java b/backend/src/main/java/br/com/servicemaker/controller/AgendaController.java index 10986c37..c0725812 100644 --- a/backend/src/main/java/br/com/servicemaker/controller/AgendaController.java +++ b/backend/src/main/java/br/com/servicemaker/controller/AgendaController.java @@ -10,7 +10,7 @@ @CrossOrigin("*") @RestController -@RequestMapping("/agenda") +@RequestMapping("/api/agenda") public class AgendaController extends AbstractController { public AgendaController(AgendaService service) { diff --git a/backend/src/main/java/br/com/servicemaker/controller/ServicoController.java b/backend/src/main/java/br/com/servicemaker/controller/ServicoController.java index 1eb8beef..176ad25d 100644 --- a/backend/src/main/java/br/com/servicemaker/controller/ServicoController.java +++ b/backend/src/main/java/br/com/servicemaker/controller/ServicoController.java @@ -5,6 +5,10 @@ import br.com.servicemaker.domain.Servico; import br.com.servicemaker.repository.ServicoRepository; import br.com.servicemaker.service.ServicoService; +import java.util.List; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -13,8 +17,16 @@ public class ServicoController extends AbstractController { + private final ServicoService servicoService; + public ServicoController(ServicoService service) { super(service); + this.servicoService = service; } + @GetMapping("/prestador/{idPrestador}") + public ResponseEntity> findAllServicosPorPrestador(@PathVariable Long idPrestador) { + List servicosPorPrestador = servicoService.findAllServicosPorPrestador(idPrestador); + return ResponseEntity.ok(servicosPorPrestador); + } } diff --git a/backend/src/main/java/br/com/servicemaker/domain/Agenda.java b/backend/src/main/java/br/com/servicemaker/domain/Agenda.java index e9ed76b0..7370cd94 100644 --- a/backend/src/main/java/br/com/servicemaker/domain/Agenda.java +++ b/backend/src/main/java/br/com/servicemaker/domain/Agenda.java @@ -23,11 +23,10 @@ public class Agenda extends AbstractEntity { @OneToMany(mappedBy = "agenda", cascade = CascadeType.REMOVE) - @JsonManagedReference private List cronogramas; @OneToMany(mappedBy = "agenda") - @JsonManagedReference + @JsonManagedReference("agenda-reservas") private List reservas; } \ No newline at end of file diff --git a/backend/src/main/java/br/com/servicemaker/domain/Avaliacao.java b/backend/src/main/java/br/com/servicemaker/domain/Avaliacao.java index 2b6f3c2b..99f21204 100644 --- a/backend/src/main/java/br/com/servicemaker/domain/Avaliacao.java +++ b/backend/src/main/java/br/com/servicemaker/domain/Avaliacao.java @@ -38,10 +38,5 @@ public class Avaliacao extends AbstractEntity { @JsonBackReference private Usuario cliente; - @ManyToOne() - @JoinColumn(name = "ID_PRESTADOR", nullable = false) - @JsonBackReference - private Prestador prestador; - } diff --git a/backend/src/main/java/br/com/servicemaker/domain/Certificado.java b/backend/src/main/java/br/com/servicemaker/domain/Certificado.java index 406fbc64..37427391 100644 --- a/backend/src/main/java/br/com/servicemaker/domain/Certificado.java +++ b/backend/src/main/java/br/com/servicemaker/domain/Certificado.java @@ -1,7 +1,7 @@ package br.com.servicemaker.domain; import br.com.servicemaker.abstractcrud.AbstractEntity; -import com.fasterxml.jackson.annotation.JsonManagedReference; +import com.fasterxml.jackson.annotation.JsonBackReference; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.JoinColumn; @@ -32,7 +32,7 @@ public class Certificado extends AbstractEntity { @ManyToOne() @JoinColumn(name = "ID_PRESTADOR", nullable = false) - @JsonManagedReference + @JsonBackReference("prestador-certificados") private Prestador prestador; } \ No newline at end of file diff --git a/backend/src/main/java/br/com/servicemaker/domain/Prestador.java b/backend/src/main/java/br/com/servicemaker/domain/Prestador.java index ac498cd3..d6b65c4a 100644 --- a/backend/src/main/java/br/com/servicemaker/domain/Prestador.java +++ b/backend/src/main/java/br/com/servicemaker/domain/Prestador.java @@ -6,6 +6,7 @@ import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; import jakarta.persistence.OneToOne; import java.util.Collection; @@ -14,6 +15,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -23,23 +25,26 @@ @AllArgsConstructor @NoArgsConstructor @DiscriminatorValue("prestador") +@ToString(exclude = "servicos") public class Prestador extends Usuario { - @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "id_agenda", nullable = false, referencedColumnName = "id") - @JsonManagedReference private Agenda agenda; @OneToMany(mappedBy = "prestador", cascade = {CascadeType.REMOVE, CascadeType.MERGE}) - @JsonManagedReference + @JsonManagedReference("prestador-servico") private List servicos; @OneToMany(mappedBy = "prestador", cascade = {CascadeType.REMOVE, CascadeType.MERGE}, orphanRemoval = true) - @JsonManagedReference + @JsonManagedReference("prestador-certificados") private List certificados; + @ManyToOne + @JoinColumn(name = "id_setor") + private Setor setor; + public Prestador(String nome, String cpf, String senha, Contato contato, Endereco endereco, Roles role, Agenda agenda) { @@ -52,4 +57,6 @@ public Collection getAuthorities() { return List.of(new SimpleGrantedAuthority(Roles.ROLE_PRESTADOR.getRole()), new SimpleGrantedAuthority(Roles.ROLE_CLIENTE.getRole())); } + + } \ No newline at end of file diff --git a/backend/src/main/java/br/com/servicemaker/domain/Reserva.java b/backend/src/main/java/br/com/servicemaker/domain/Reserva.java index dbb8967d..91f59c56 100644 --- a/backend/src/main/java/br/com/servicemaker/domain/Reserva.java +++ b/backend/src/main/java/br/com/servicemaker/domain/Reserva.java @@ -27,24 +27,19 @@ public class Reserva extends AbstractEntity { @ManyToOne() @JoinColumn(name = "ID_CLIENTE", nullable = false) - @JsonBackReference + @JsonBackReference("clientes-reservas") private Usuario cliente; @ManyToOne() @JoinColumn(name = "ID_AGENDA", nullable = false) - @JsonBackReference + @JsonBackReference("agenda-reservas") private Agenda agenda; @ManyToOne() @JoinColumn(name = "ID_SERVICO", nullable = false) - @JsonBackReference + @JsonBackReference("reservas-servicos") private Servico servico; - @ManyToOne() - @JoinColumn(name = "id_prestador", nullable = false) - @JsonBackReference - private Prestador prestador; - @Enumerated(EnumType.STRING) private Status status; diff --git a/backend/src/main/java/br/com/servicemaker/domain/Servico.java b/backend/src/main/java/br/com/servicemaker/domain/Servico.java index a43040d4..c62541a2 100644 --- a/backend/src/main/java/br/com/servicemaker/domain/Servico.java +++ b/backend/src/main/java/br/com/servicemaker/domain/Servico.java @@ -15,6 +15,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.ToString; @EqualsAndHashCode(callSuper = false) @Entity @@ -22,13 +23,9 @@ @Data @AllArgsConstructor @NoArgsConstructor +@ToString(exclude = "prestador") public class Servico extends AbstractEntity { - @ManyToOne - @JoinColumn(name = "ID_SETOR", nullable = false) - @JsonBackReference - private Setor setor; - private String descricao; @Column(name = "tempo_servico") @@ -38,11 +35,11 @@ public class Servico extends AbstractEntity { @ManyToOne @JoinColumn(name = "ID_PRESTADOR", nullable = false) - @JsonBackReference + @JsonBackReference("prestador-servico") private Prestador prestador; @OneToMany(mappedBy = "servico") - @JsonManagedReference + @JsonManagedReference("reservas-servicos") private List reservas; } \ No newline at end of file diff --git a/backend/src/main/java/br/com/servicemaker/domain/Usuario.java b/backend/src/main/java/br/com/servicemaker/domain/Usuario.java index eb68245b..09dbe3f8 100644 --- a/backend/src/main/java/br/com/servicemaker/domain/Usuario.java +++ b/backend/src/main/java/br/com/servicemaker/domain/Usuario.java @@ -60,13 +60,12 @@ public class Usuario extends AbstractEntity implements UserDetails { @Enumerated(EnumType.STRING) private Roles role; - @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "id_contato") - @JsonManagedReference private Contato contato; @OneToMany(mappedBy = "cliente", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - @JsonManagedReference + @JsonManagedReference("clientes-reservas") private List reservas; @OneToMany(mappedBy = "cliente", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY) diff --git a/backend/src/main/java/br/com/servicemaker/repository/ServicoRepository.java b/backend/src/main/java/br/com/servicemaker/repository/ServicoRepository.java index e8ad7c19..5dcc19d2 100644 --- a/backend/src/main/java/br/com/servicemaker/repository/ServicoRepository.java +++ b/backend/src/main/java/br/com/servicemaker/repository/ServicoRepository.java @@ -2,9 +2,14 @@ import br.com.servicemaker.abstractcrud.AbstractRepository; import br.com.servicemaker.domain.Servico; +import java.util.List; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @Repository public interface ServicoRepository extends AbstractRepository { + @Query("SELECT s FROM Servico s WHERE s.prestador.id = :idPrestador ") + List findAllServicosPorPrestador(@Param("idPrestador") Long idPrestador); } diff --git a/backend/src/main/java/br/com/servicemaker/service/ServicoService.java b/backend/src/main/java/br/com/servicemaker/service/ServicoService.java index 1a3620a5..04a30837 100644 --- a/backend/src/main/java/br/com/servicemaker/service/ServicoService.java +++ b/backend/src/main/java/br/com/servicemaker/service/ServicoService.java @@ -4,15 +4,22 @@ import br.com.servicemaker.domain.Servico; import br.com.servicemaker.repository.ServicoRepository; import jakarta.persistence.EntityManager; +import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class ServicoService extends AbstractService { + private final ServicoRepository servicoRepository; + @Autowired public ServicoService(ServicoRepository repository, EntityManager em) { super(repository, em); + this.servicoRepository = repository; } + public List findAllServicosPorPrestador(Long idPrestador) { + return servicoRepository.findAllServicosPorPrestador(idPrestador); + } } diff --git a/backend/src/main/resources/META-INF/MANIFEST.MF b/backend/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000..387c0fd3 --- /dev/null +++ b/backend/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: br.com.servicemaker.SerivceMakerApplication + diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 7ef10966..44316f00 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1,7 +1,7 @@ spring.application.name=serivceMaker -spring.datasource.url=jdbc:postgresql://localhost:5432/servicemaker +spring.datasource.url=jdbc:postgresql://autorack.proxy.rlwy.net:44626/railway spring.datasource.username=postgres -spring.datasource.password=root +spring.datasource.password=VkSHVJkKYqUAopijrQfXuNeAYnkygFLT spring.datasource.driver-class-name=org.postgresql.Driver api.security.token.secret=${JWT_SECRET:my-secret-key} spring.jpa.show-sql=true diff --git a/backend/src/main/resources/db/migration/V5__insert_setores.sql b/backend/src/main/resources/db/migration/V5__insert_setores.sql index e8dacba8..3c7ed7f7 100644 --- a/backend/src/main/resources/db/migration/V5__insert_setores.sql +++ b/backend/src/main/resources/db/migration/V5__insert_setores.sql @@ -1,4 +1,4 @@ -INSERT INTO servicemaker.public.setor (DESCRICAO) +INSERT INTO setor (DESCRICAO) VALUES ('Encanador'), ('Eletricista'), diff --git a/backend/src/main/resources/db/migration/V6__criar_coluna_idsetor.sql b/backend/src/main/resources/db/migration/V6__criar_coluna_idsetor.sql new file mode 100644 index 00000000..59708494 --- /dev/null +++ b/backend/src/main/resources/db/migration/V6__criar_coluna_idsetor.sql @@ -0,0 +1,8 @@ +ALTER TABLE IF EXISTS usuario + ADD COLUMN IF NOT EXISTS id_setor bigint; + +ALTER TABLE IF EXISTS usuario + ADD CONSTRAINT usuario_setor_fk FOREIGN KEY (id_setor) REFERENCES setor (id); + +alter table if exists servico + drop column if exists id_setor \ No newline at end of file diff --git a/frontend/app/(agenda)/agendamento.tsx b/frontend/app/(agenda)/agendamento.tsx index ced20ac7..7b396591 100644 --- a/frontend/app/(agenda)/agendamento.tsx +++ b/frontend/app/(agenda)/agendamento.tsx @@ -1,111 +1,132 @@ import React, { useEffect, useState } from 'react'; -import { ScrollView, StyleSheet, Text, View, Button, StatusBar, Alert, TextInput, Pressable } from 'react-native'; +import { StyleSheet, Text, View, StatusBar, Pressable } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; -import DateTimePicker, { DateTimePickerEvent } from '@react-native-community/datetimepicker'; import { Controller, useForm } from 'react-hook-form'; import { SafeAreaView } from 'react-native-safe-area-context'; -import { router } from 'expo-router'; -import { obterNomeUsuario } from '@/utils/storageUtils'; +import { router, useLocalSearchParams } from 'expo-router'; +import { DateInput } from '@/components/DateInput'; +import { TimeInput } from '@/components/HoraInput'; +import PrestadorService from '../../service/prestadorservice' +import ServicoService from '../../service/ServicoService' +import ReservaService from '../../service/ReservaService' +import { AutocompleteInput } from '@/components/AutocompleteInput'; +import { useUser } from '@/components/contextoApi'; -const [nomeUsuario, setNomeUsuario] = useState('Usuário'); +type AgendamentoForm = { + servico: any; + prestador: any; + data: Date | null; + horaInicio: string; + horaFim: string; + status: any, + usuario: any +}; -useEffect(() => { - const carregarNomeUsuario = async () => { - const nome = await obterNomeUsuario(); - setNomeUsuario(nome); - }; +const calculateHoraFim = (horaInicio: string, tempoServico: string) => { - carregarNomeUsuario(); -}, []); + if (!horaInicio || !tempoServico) { + return ''; + } + const [hours, minutes] = horaInicio.split(':').map(Number); + const [serviceHours, serviceMinutes] = tempoServico.split(':').map(Number); + const totalMinutes = hours * 60 + minutes + serviceHours * 60 + serviceMinutes; -type AgendamentoForm = { - servico: string; - prestador: string; - localizacao: string; - anotacao: string; - data: string; - hora: string; - horaFim: string; + const finalHours = Math.floor(totalMinutes / 60) % 24; + const finalMinutes = totalMinutes % 60; + + return `${finalHours.toString().padStart(2, '0')}:${finalMinutes.toString().padStart(2, '0')}`; }; -const prestadorClick = ()=>{ - router.navigate('/(servico)/prestador') -} export default function Agendamento() { - const { control, handleSubmit, formState: { errors, isValid } } = useForm({ - defaultValues: { - servico: '', - prestador: '', - localizacao: '', - anotacao: '', - data: '', - hora: '', - }, - mode: 'onChange', - }); - const [selectedDate, setSelectedDate] = useState(undefined); - const [showDatePicker, setShowDatePicker] = useState(false); - const [showTimePicker, setShowTimePicker] = useState(false); - const [mode, setMode] = useState<'date' | 'time'>('date'); - const [show, setShow] = useState(false); - - const onChange = (event: DateTimePickerEvent, selectedValue?: Date) => { - const currentDate = selectedValue || selectedDate; - setShowDatePicker(false); - setShowTimePicker(false); - setSelectedDate(currentDate); - }; + const { nomeUsuario } = useUser(); + + const [prestadores, setPrestadores] = useState([]); + const [servicos, setServicos] = useState([]); - const showMode = (currentMode: 'date' | 'time') => { - setMode(currentMode); - setShow(true); + const { idPrestador, idServico, dataAgendamento } = useLocalSearchParams(); + + const parsedDataAgendamento = dataAgendamento ? new Date(dataAgendamento.toString()) : null; + const parsedIdServico = idServico ? parseInt(idServico.toString()) : null + const parsedIdPrestador = idPrestador ? parseInt(idPrestador.toString()) : null + + const agendaClick = () => { + router.navigate('/(tabs)/agenda'); }; - const addTask = async (data: AgendamentoForm) => { - if (!selectedDate || !data.servico || !data.prestador || !data.localizacao || !data.anotacao) { - Alert.alert('Erro', 'Por favor, preencha todos os campos e selecione uma data.'); - return; + const fetchPrestadores = async () => { + try { + const response = await PrestadorService.getAllPrestadores(); + setPrestadores(response); + } catch (error) { + console.error('Erro ao buscar prestadores:', error); } - console.log('Agendamento adicionado:', { ...data, date: selectedDate }); - Alert.alert('Agendamento adicionado com sucesso!'); - router.push('/(tabs)/inicio'); }; - const formatTime = (value: string) => { - const onlyNumbers = value.replace(/\D/g, ''); - let formattedValue = onlyNumbers.slice(0, 4); + const fetchDataFromUrl = async () => { + try { + if (parsedIdPrestador) { + const prestador = await PrestadorService.getPrestadorById(parsedIdPrestador); + setValue('prestador', prestador?.nome || ''); + setServicos(prestador?.servicos || []); + } + if (parsedIdServico) { + const servico = await ServicoService.getServicoById(parsedIdServico); + setValue('servico', servico?.descricao || ''); + } + } catch (error) { + console.error('Erro ao buscar dados da URL:', error); + } + }; - if (formattedValue.length >= 3) { - formattedValue = `${formattedValue.slice(0, 2)}h:${formattedValue.slice(2)}m`; - } else if (formattedValue.length >= 1) { - formattedValue = `${formattedValue}h`; + useEffect(() => { + if (parsedIdPrestador || parsedIdServico) { + fetchDataFromUrl(); + } else { + fetchPrestadores(); } + }, []); - return formattedValue; - }; + const { control, handleSubmit, formState: { errors, isValid }, watch, setValue, getValues } = useForm({ + defaultValues: { + prestador: '', + servico: '', + data: parsedDataAgendamento, + horaInicio: '', + horaFim: '', + }, + mode: 'onChange', + }); - const formatDate = (value: string) => { - const onlyNumbers = value.replace(/\D/g, ''); - let formattedValue = onlyNumbers.slice(0, 8); - if (formattedValue.length >= 6) { - formattedValue = `${formattedValue.slice(0, 2)}/${formattedValue.slice(2, 4)}/${formattedValue.slice(4)}`; - } else if (formattedValue.length >= 4) { - formattedValue = `${formattedValue.slice(0, 2)}/${formattedValue.slice(2)}`; - } else if (formattedValue.length >= 2) { - formattedValue = `${formattedValue.slice(0, 2)}`; - } + const handleHoraFimUpdate = (horaInicio: any, servicoSelecionado: any) => { + const servicoEncontrado = servicos.find(s => s.descricao === servicoSelecionado); + const tempoServico = servicoEncontrado?.tempoServico ?? ''; - return formattedValue; - }; + const newHoraFim = calculateHoraFim(horaInicio, tempoServico); + console.log("Calculando horaFim: ", newHoraFim); - const agendaClick =()=>{ - router.navigate('/(tabs)/agenda'); + setValue('horaFim', newHoraFim, { shouldDirty: true, shouldTouch: true }); }; + const saveReserva = async (reserva: AgendamentoForm) => { + reserva.usuario = { id: 2 }; + reserva.status = "PENDENTE"; + console.log(reserva); + + try { + // await ReservaService.createReserva(reserva); + router.navigate("/agenda"); + + } catch (error) { + console.error('Erro ao cadastrar reserva:', error); + + } + + } + return ( ); @@ -292,4 +293,8 @@ const styles = StyleSheet.create({ backIcon: { paddingRight: 15, }, + dataTempo: { + paddingRight: 25, + paddingLeft: 3 + } }); diff --git a/frontend/app/(agenda)/cronograma.tsx b/frontend/app/(agenda)/cronograma.tsx index 4610b371..a782c257 100644 --- a/frontend/app/(agenda)/cronograma.tsx +++ b/frontend/app/(agenda)/cronograma.tsx @@ -1,22 +1,12 @@ -import React, { useEffect, useState } from 'react'; +import React, { } from 'react'; import { View, Text, TextInput, StyleSheet, Button, Alert, Pressable, ScrollView, StatusBar } from 'react-native'; import { useForm, Controller, useFieldArray } from 'react-hook-form'; import { Ionicons } from '@expo/vector-icons'; import { SafeAreaView } from 'react-native-safe-area-context'; import MultiSelect from 'react-native-multiple-select'; import { router } from 'expo-router'; -import { obterNomeUsuario } from '@/utils/storageUtils'; +import { useUser } from '@/components/contextoApi'; -const [nomeUsuario, setNomeUsuario] = useState('Usuário'); - -useEffect(() => { - const carregarNomeUsuario = async () => { - const nome = await obterNomeUsuario(); - setNomeUsuario(nome); - }; - - carregarNomeUsuario(); -}, []); type CronogramaForm = { cronogramas: { @@ -37,6 +27,8 @@ const diasSemana = [ ]; export default function Cronograma() { + const { nomeUsuario } = useUser(); + const { control, handleSubmit, formState: { errors } } = useForm({ defaultValues: { cronogramas: [{ diff --git a/frontend/app/(auth)/login.tsx b/frontend/app/(auth)/login.tsx index eab27218..fa3a6409 100644 --- a/frontend/app/(auth)/login.tsx +++ b/frontend/app/(auth)/login.tsx @@ -5,7 +5,7 @@ import { SafeAreaView } from 'react-native-safe-area-context'; import axios from 'axios'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { router } from 'expo-router'; -import UsuarioService from '../../service/UsuarioService' +import { useUser } from '../../components/contextoApi'; type LoginForm = { email: string; @@ -32,12 +32,10 @@ const storeToken = async (data: any) => { if (typeof window !== 'undefined' && window.localStorage) { // Ambiente navegador window.localStorage.setItem('jwt_token', data.token); - window.localStorage.setItem('nome_usuario', data.nome) console.log('windows') } else { // Ambiente móvel await AsyncStorage.setItem('jwt_token', data.token); - await AsyncStorage.setItem('nome_usuario', data.nome); console.log('movel') } } catch (error) { @@ -45,12 +43,13 @@ const storeToken = async (data: any) => { } }; -async function handleLogin(requestData: LoginForm) { +async function handleLogin(requestData: LoginForm, setNomeUsuario: (name: string) => void) { try { const responseData = await login(requestData); - + console.log('Resposta do login:', responseData); + setNomeUsuario(responseData.nome) await storeToken(responseData); - + router.push("/(tabs)/inicio"); } catch (error) { @@ -67,6 +66,8 @@ const LoginScreen = () => { mode: "onChange" }); + const { setNomeUsuario } = useUser(); + return ( { /> {{errors?.senha?.message}} - + handleLogin(data, setNomeUsuario))} + disabled={!isValid} > Continuar diff --git a/frontend/app/(perfil)/avaliacao.tsx b/frontend/app/(perfil)/avaliacao.tsx index 0da53af3..7d0aad41 100644 --- a/frontend/app/(perfil)/avaliacao.tsx +++ b/frontend/app/(perfil)/avaliacao.tsx @@ -1,20 +1,10 @@ +import { useUser } from '@/components/contextoApi'; import { Ionicons } from '@expo/vector-icons'; import { router } from 'expo-router'; -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { SafeAreaView, StyleSheet, View, Text, Pressable, Alert, TextInput, StatusBar } from 'react-native'; import Icon from 'react-native-vector-icons/MaterialIcons'; -import { obterNomeUsuario } from '@/utils/storageUtils'; -const [nomeUsuario, setNomeUsuario] = useState('Usuário'); - -useEffect(() => { - const carregarNomeUsuario = async () => { - const nome = await obterNomeUsuario(); - setNomeUsuario(nome); - }; - - carregarNomeUsuario(); -}, []); const perfilClick = ()=>{ router.navigate('/(tabs)/perfil') @@ -23,6 +13,7 @@ const perfilClick = ()=>{ export default function Avaliacao() { const [rating, setRating] = useState(0); const [feedback, setFeedback] = useState(''); + const { nomeUsuario } = useUser(); const handleSubmit = () => { if (rating === 0) { diff --git a/frontend/app/(perfil)/compartilhe.tsx b/frontend/app/(perfil)/compartilhe.tsx index 7fef06e5..4c86e710 100644 --- a/frontend/app/(perfil)/compartilhe.tsx +++ b/frontend/app/(perfil)/compartilhe.tsx @@ -1,26 +1,13 @@ -import React, { useEffect, useState } from 'react'; -import { Text, SafeAreaView, StyleSheet, View, StatusBar, Pressable } from 'react-native'; +import React from 'react'; +import { Text, SafeAreaView, StyleSheet, View, StatusBar, Pressable, Share } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; -import { Share } from 'react-native'; import { router } from 'expo-router'; -import { obterNomeUsuario } from '@/utils/storageUtils'; +import { useUser } from '@/components/contextoApi'; -const [nomeUsuario, setNomeUsuario] = useState('Usuário'); - -useEffect(() => { - const carregarNomeUsuario = async () => { - const nome = await obterNomeUsuario(); - setNomeUsuario(nome); - }; - - carregarNomeUsuario(); -}, []); - -const perfilClick = ()=>{ - router.navigate('/(tabs)/perfil') -} export default function Compartilhar() { + const { nomeUsuario } = useUser(); + const onShare = async () => { try { await Share.share({ @@ -35,7 +22,7 @@ export default function Compartilhar() { } }; - const perfilClick =()=>{ + const perfilClick = () => { router.navigate('/(tabs)/perfil'); }; @@ -55,7 +42,7 @@ export default function Compartilhar() { - Compartilhe + Compartilhe Compartilhe nosso aplicativo com seus amigos e familiares! diff --git a/frontend/app/(perfil)/criaservico.tsx b/frontend/app/(perfil)/criaservico.tsx index e1dd40e1..72141728 100644 --- a/frontend/app/(perfil)/criaservico.tsx +++ b/frontend/app/(perfil)/criaservico.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { } from 'react'; import { SafeAreaView, Text, View, TextInput, StyleSheet, ScrollView, Pressable } from 'react-native'; import { useForm, Controller } from 'react-hook-form'; import { Ionicons } from '@expo/vector-icons'; @@ -6,28 +6,14 @@ import { Picker } from '@react-native-picker/picker'; import ServicoService from '../../service/ServicoService' import { Setor } from '@/constants/SetorEnum'; import { router } from 'expo-router'; -import { obterNomeUsuario } from '@/utils/storageUtils'; +import { useUser } from '@/components/contextoApi'; -const [nomeUsuario, setNomeUsuario] = useState('Usuário'); - -useEffect(() => { - const carregarNomeUsuario = async () => { - const nome = await obterNomeUsuario(); - setNomeUsuario(nome); - }; - - carregarNomeUsuario(); -}, []); - -const usuarioLogado = { id: 1, nome: 'Usúario' }; +const usuarioLogado = { id: 1, nome: 'Usuário' }; const perfilClick =()=>{ router.navigate('/(tabs)/perfil'); }; -const salvarClick =()=>{ - router.navigate('/(servico)/prestador'); -}; type criarServicoForm = { servico: string; @@ -37,7 +23,9 @@ type criarServicoForm = { setor: Setor; } -export default function criaServico() { +export default function CriaServico() { + const { nomeUsuario } = useUser(); + const { control, handleSubmit, formState: { errors } } = useForm({ defaultValues: { descricao: '', @@ -55,20 +43,19 @@ export default function criaServico() { return parseFloat(preco); } const toDateTime = (tempo: string) => { - const match = RegExp(/(\d+)h:(\d+)m/).exec(tempo); - + const match = RegExp(/(\d+)h(?::(\d+)m)?/).exec(tempo); + if (!match) { throw new Error("Formato de tempo inválido"); } - + const hours = parseInt(match[1], 10); - const minutes = parseInt(match[2], 10); - + const minutes = parseInt(match[2] || "0", 10); + const date = new Date(); date.setHours(hours, minutes, 0, 0); return date.toLocaleTimeString("pt-BR"); - } - + }; const onSubmit = async (data: criarServicoForm) => { @@ -126,7 +113,7 @@ export default function criaServico() { /> - Usuário + {nomeUsuario} @@ -315,13 +302,4 @@ const styles = StyleSheet.create({ backIcon: { paddingRight: 15, }, - tituloContainer: { - alignItems: 'center', - marginBottom: 20, - }, - titulo: { - fontSize: 22, - fontWeight: 'bold', - color: '#333', - }, }); \ No newline at end of file diff --git a/frontend/app/(perfil)/edicaoperfil.tsx b/frontend/app/(perfil)/edicaoperfil.tsx index f0bd4e7a..302f635f 100644 --- a/frontend/app/(perfil)/edicaoperfil.tsx +++ b/frontend/app/(perfil)/edicaoperfil.tsx @@ -7,28 +7,17 @@ import UsuarioService from '../../service/UsuarioService' import ContatoService from '../../service/ContatoService' import EnderecoService from '../../service/EnderecoService' import AsyncStorage from '@react-native-async-storage/async-storage'; -import { obterNomeUsuario } from '@/utils/storageUtils'; +import { useUser } from '@/components/contextoApi'; -const [nomeUsuario, setNomeUsuario] = useState('Usuário'); -useEffect(() => { - const carregarNomeUsuario = async () => { - const nome = await obterNomeUsuario(); - setNomeUsuario(nome); - }; - - carregarNomeUsuario(); -}, []); - -const perfilClick = ()=>{ - router.navigate('/(tabs)/perfil') -} export default function EdicaoPerfil() { const [nome, setNome] = useState(''); const [email, setEmail] = useState(''); const [telefone, setTelefone] = useState(''); const [endereco, setEndereco] = useState(''); + const { nomeUsuario } = useUser(); + useEffect(() => { const fetchData = async () => { diff --git a/frontend/app/(perfil)/endereco.tsx b/frontend/app/(perfil)/endereco.tsx index 6abb82e1..9e70e6d0 100644 --- a/frontend/app/(perfil)/endereco.tsx +++ b/frontend/app/(perfil)/endereco.tsx @@ -1,30 +1,17 @@ import { Ionicons } from '@expo/vector-icons'; -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { SafeAreaView, StyleSheet, View, Text, TextInput, Pressable, FlatList, StatusBar } from 'react-native'; import Icon from 'react-native-vector-icons/MaterialIcons'; import { useForm, Controller } from 'react-hook-form'; import { router } from 'expo-router'; -import { obterNomeUsuario } from '@/utils/storageUtils'; +import { useUser } from '@/components/contextoApi'; -const [nomeUsuario, setNomeUsuario] = useState('Usuário'); - -useEffect(() => { - const carregarNomeUsuario = async () => { - const nome = await obterNomeUsuario(); - setNomeUsuario(nome); - }; - - carregarNomeUsuario(); -}, []); - - -const perfilClick = ()=>{ - router.navigate('/(tabs)/perfil') -} export default function GerenciarEndereco() { const { control, handleSubmit, reset } = useForm(); const [enderecos, setEnderecos] = useState([]); + const { nomeUsuario } = useUser(); + const onSubmit = (data: { novoEndereco: string; }) => { if (data.novoEndereco.trim()) { diff --git a/frontend/app/(perfil)/historico.tsx b/frontend/app/(perfil)/historico.tsx index c7de8acc..74a32ec8 100644 --- a/frontend/app/(perfil)/historico.tsx +++ b/frontend/app/(perfil)/historico.tsx @@ -1,22 +1,13 @@ +import { useUser } from '@/components/contextoApi'; import { Ionicons } from '@expo/vector-icons'; import { router } from 'expo-router'; -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { View, Text, StyleSheet, SafeAreaView, StatusBar, Pressable } from 'react-native'; import { ScrollView } from 'react-native-gesture-handler'; -import { obterNomeUsuario } from '@/utils/storageUtils'; - -const [nomeUsuario, setNomeUsuario] = useState('Usuário'); - -useEffect(() => { - const carregarNomeUsuario = async () => { - const nome = await obterNomeUsuario(); - setNomeUsuario(nome); - }; - - carregarNomeUsuario(); -}, []); const ServicosLista = () => { + const { nomeUsuario } = useUser(); + const servicos = [ { titulo: 'Conserto de Ar-Condicionado', empresa: 'CoolTech', data: '03/05/2024', avaliacao: 4, custo: 250.0 }, diff --git a/frontend/app/(perfil)/sobre.tsx b/frontend/app/(perfil)/sobre.tsx index c37a5fdc..25e1b3a4 100644 --- a/frontend/app/(perfil)/sobre.tsx +++ b/frontend/app/(perfil)/sobre.tsx @@ -1,30 +1,17 @@ +import { useUser } from '@/components/contextoApi'; import { Ionicons } from '@expo/vector-icons'; import { router } from 'expo-router'; -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { SafeAreaView, StyleSheet, View, Text, ScrollView, StatusBar, Pressable } from 'react-native'; -import { obterNomeUsuario } from '@/utils/storageUtils'; - -const [nomeUsuario, setNomeUsuario] = useState('Usuário'); - -useEffect(() => { - const carregarNomeUsuario = async () => { - const nome = await obterNomeUsuario(); - setNomeUsuario(nome); - }; - - carregarNomeUsuario(); -}, []); - -const perfilClick = ()=>{ - router.navigate('/(tabs)/perfil') -} export default function SobreNos() { const perfilClick =()=>{ router.navigate('/(tabs)/perfil'); }; + const { nomeUsuario } = useUser(); return ( +