diff --git a/app/.gitignore b/app/.gitignore index b46299f..9d913ec 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1,2 +1,3 @@ /build -/google-services.json \ No newline at end of file +/google-services.json +/secret.properties \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 689386e..e975ae2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,9 +1,14 @@ +import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties + plugins { alias(libs.plugins.android.application) alias(libs.plugins.google.gms.google.services) alias(libs.plugins.kotlin.android) } +val token = gradleLocalProperties(rootDir, providers) + .getProperty("API_TOKEN", "") + buildscript { repositories { google() @@ -30,6 +35,12 @@ android { versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + buildConfigField( + "String", + "API_TOKEN", + "\"${token}\"" + ) } buildTypes { @@ -82,4 +93,7 @@ dependencies { implementation("org.java-websocket:Java-WebSocket:1.5.3") implementation("io.reactivex.rxjava2:rxjava:2.2.21") implementation("io.reactivex.rxjava2:rxandroid:2.1.1") + + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.4") + implementation("androidx.lifecycle:lifecycle-process:2.8.4") } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b85dc8e..4feac2a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -35,9 +35,9 @@ - - - + diff --git a/app/src/main/java/com/example/projetosaveit/adapter/AdapterChat.kt b/app/src/main/java/com/example/projetosaveit/adapter/AdapterChat.kt index d6d8200..b56aec2 100644 --- a/app/src/main/java/com/example/projetosaveit/adapter/AdapterChat.kt +++ b/app/src/main/java/com/example/projetosaveit/adapter/AdapterChat.kt @@ -51,7 +51,6 @@ class AdapterChat : RecyclerView.Adapter() { holder.itemConversa.setOnClickListener { val intent = Intent(holder.itemView.context, Conversa::class.java) - intent.putExtra("empresaFoto", empresa?.enterpriseImage) intent.putExtra("empresaId", empresa?.id) intent.putExtra("chatId", chat.chatId) holder.itemView.context.startActivity(intent) diff --git a/app/src/main/java/com/example/projetosaveit/adapter/AdapterChatbot.kt b/app/src/main/java/com/example/projetosaveit/adapter/AdapterChatbot.kt new file mode 100644 index 0000000..96d2f1b --- /dev/null +++ b/app/src/main/java/com/example/projetosaveit/adapter/AdapterChatbot.kt @@ -0,0 +1,60 @@ +package com.example.projetosaveit.adapter + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.example.projetosaveit.R +import com.example.projetosaveit.adapter.recycleView.MensagemChatbot +import com.example.projetosaveit.adapter.recycleView.TipoMensagemChatbot + +class AdapterChatbot( + private val mensagens: MutableList +) : RecyclerView.Adapter() { + + private val VIEW_USUARIO = 1 + private val VIEW_BOT = 2 + + override fun getItemViewType(position: Int): Int { + return when (mensagens[position].tipo) { + TipoMensagemChatbot.USUARIO -> VIEW_USUARIO + TipoMensagemChatbot.BOT -> VIEW_BOT + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return if (viewType == VIEW_USUARIO) { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.bolha_mensagem_direita, parent, false) + UsuarioViewHolder(view) + } else { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.bolha_mensagem_esquerda, parent, false) + BotViewHolder(view) + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + val mensagem = mensagens[position] + when (holder) { + is UsuarioViewHolder -> holder.msg.text = mensagem.texto + is BotViewHolder -> holder.msg.text = mensagem.texto + } + } + + override fun getItemCount(): Int = mensagens.size + + fun adicionarMensagem(mensagem: MensagemChatbot) { + mensagens.add(mensagem) + notifyItemInserted(mensagens.size - 1) + } + + class UsuarioViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val msg: TextView = itemView.findViewById(R.id.mensagem_direita) + } + + class BotViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val msg: TextView = itemView.findViewById(R.id.mensagem_esquerda) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/projetosaveit/adapter/AdapterConversa.kt b/app/src/main/java/com/example/projetosaveit/adapter/AdapterConversa.kt index 91efc77..6b01a88 100644 --- a/app/src/main/java/com/example/projetosaveit/adapter/AdapterConversa.kt +++ b/app/src/main/java/com/example/projetosaveit/adapter/AdapterConversa.kt @@ -5,11 +5,9 @@ import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.recyclerview.widget.RecyclerView -import com.bumptech.glide.Glide import com.example.projetosaveit.R import com.example.projetosaveit.adapter.recycleView.Mensagem import com.example.projetosaveit.adapter.recycleView.TipoMensagem -import com.google.android.material.imageview.ShapeableImageView class AdapterConversa(private val mensagens: MutableList) : RecyclerView.Adapter() { @@ -21,12 +19,10 @@ class AdapterConversa(private val mensagens: MutableList) : inner class EnviadaViewHolder(view: View) : RecyclerView.ViewHolder(view) { val textView: TextView = view.findViewById(R.id.mensagem_direita) - val foto: ShapeableImageView = view.findViewById(R.id.fotoEmpresaDireita) } inner class RecebidaViewHolder(view: View) : RecyclerView.ViewHolder(view) { val textView: TextView = view.findViewById(R.id.mensagem_esquerda) - val foto: ShapeableImageView = view.findViewById(R.id.fotoEmpresaEsquerda) } override fun getItemViewType(position: Int): Int { @@ -45,18 +41,8 @@ class AdapterConversa(private val mensagens: MutableList) : override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { val mensagem = mensagens[position] when (holder) { - is EnviadaViewHolder -> { - holder.textView.text = mensagem.texto - Glide.with(holder.itemView.context) - .load(mensagem.fotoUrl) - .into(holder.foto) - } - is RecebidaViewHolder -> { - holder.textView.text = mensagem.texto - Glide.with(holder.itemView.context) - .load(mensagem.fotoUrl) - .into(holder.foto) - } + is EnviadaViewHolder -> holder.textView.text = mensagem.texto + is RecebidaViewHolder -> holder.textView.text = mensagem.texto } } diff --git a/app/src/main/java/com/example/projetosaveit/adapter/AdapterSessoes.kt b/app/src/main/java/com/example/projetosaveit/adapter/AdapterSessoes.kt new file mode 100644 index 0000000..56f4d4c --- /dev/null +++ b/app/src/main/java/com/example/projetosaveit/adapter/AdapterSessoes.kt @@ -0,0 +1,44 @@ +package com.example.projetosaveit.adapter + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.example.projetosaveit.R + +data class ConversaItem(val titulo: String, val sessionId: String) + +class AdapterSessoes( + private val conversas: MutableList, + private val onClick: (ConversaItem) -> Unit +) : RecyclerView.Adapter() { + + inner class ConversaViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val tituloTextView: TextView = itemView.findViewById(R.id.textTituloConversa) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ConversaViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_conversa_drawer, parent, false) + return ConversaViewHolder(view) + } + + override fun onBindViewHolder(holder: ConversaViewHolder, position: Int) { + val item = conversas[position] + holder.tituloTextView.text = item.titulo + holder.itemView.setOnClickListener { onClick(item) } + } + + override fun getItemCount(): Int = conversas.size + + fun adicionarConversa(titulo: String, sessionId: String) { + conversas.add(ConversaItem(titulo, sessionId)) + notifyItemInserted(conversas.size - 1) + } + + fun limpar() { + conversas.clear() + notifyDataSetChanged() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/projetosaveit/adapter/recycleView/Mensagem.kt b/app/src/main/java/com/example/projetosaveit/adapter/recycleView/Mensagem.kt index 6b5c231..64aeba1 100644 --- a/app/src/main/java/com/example/projetosaveit/adapter/recycleView/Mensagem.kt +++ b/app/src/main/java/com/example/projetosaveit/adapter/recycleView/Mensagem.kt @@ -3,7 +3,6 @@ package com.example.projetosaveit.adapter.recycleView data class Mensagem ( val texto: String, val tipo: TipoMensagem, - val fotoUrl: String? = null, val idEmpresa: Long ) diff --git a/app/src/main/java/com/example/projetosaveit/adapter/recycleView/MensagemChatbot.kt b/app/src/main/java/com/example/projetosaveit/adapter/recycleView/MensagemChatbot.kt new file mode 100644 index 0000000..b6dfe38 --- /dev/null +++ b/app/src/main/java/com/example/projetosaveit/adapter/recycleView/MensagemChatbot.kt @@ -0,0 +1,11 @@ +package com.example.projetosaveit.adapter.recycleView + +data class MensagemChatbot( + val texto: String, + val tipo: TipoMensagemChatbot +) + +enum class TipoMensagemChatbot { + USUARIO, + BOT +} \ No newline at end of file diff --git a/app/src/main/java/com/example/projetosaveit/api/network/ApiService.kt b/app/src/main/java/com/example/projetosaveit/api/network/ApiService.kt index c1abb1c..5df504e 100644 --- a/app/src/main/java/com/example/projetosaveit/api/network/ApiService.kt +++ b/app/src/main/java/com/example/projetosaveit/api/network/ApiService.kt @@ -5,6 +5,8 @@ import com.example.projetosaveit.adapter.recycleView.Venda import com.example.projetosaveit.adapter.recycleView.Produto import com.example.projetosaveit.adapter.recycleView.Vitrine import com.example.projetosaveit.model.ChatDTO +import com.example.projetosaveit.model.ChatRequest +import com.example.projetosaveit.model.ChatResponse //import com.example.projetosaveit.model.ChatRequest //import com.example.projetosaveit.model.ChatResponse import com.example.projetosaveit.model.EmpresaDTO @@ -12,8 +14,12 @@ import com.example.projetosaveit.model.EmpresaInsertDTO import com.example.projetosaveit.model.EstoqueDTO import com.example.projetosaveit.model.FuncionarioDTO import com.example.projetosaveit.model.FuncionarioInsertDTO +import com.example.projetosaveit.model.HistoricoResponse +import com.example.projetosaveit.model.HistoricoSessaoRequest //import com.example.projetosaveit.model.HistoricoResponse import com.example.projetosaveit.model.ImagemDTO +import com.example.projetosaveit.model.IniciarChatRequest +import com.example.projetosaveit.model.IniciarChatResponse //import com.example.projetosaveit.model.IniciarChatRequest //import com.example.projetosaveit.model.IniciarChatResponse import com.example.projetosaveit.model.LoteDTO @@ -26,6 +32,7 @@ import com.example.projetosaveit.model.VitrineInsertDTO import okhttp3.ResponseBody import retrofit2.Call import retrofit2.http.Body +import retrofit2.http.DELETE import retrofit2.http.GET import retrofit2.http.PATCH import retrofit2.http.POST @@ -40,6 +47,9 @@ interface ApiService { fun getRelatorioProduto(@Path("enterpriseId") enterpriseId: Long, @Path("productId") productId: Long ): Call> + @DELETE("/api/enterprise/excluir/{id}") + fun deleteEmpresa(@Path("id") enterpriseId : Long) : Call + @GET("api/stock/relatorioProduto/{enterpriseId}") fun getRelatorioProdutos(@Path("enterpriseId") idEmpresa : Long): Call> @@ -108,6 +118,12 @@ interface ApiService { @Query("ultimoCheck") ultimoCheck: String ): Call> + @POST("api/enterprise/registrarEntrada/{enterpriseId}") + fun registrarEntrada(@Path("enterpriseId") idEmpresa: Int): Call + + @POST("api/enterprise/registrarSaida/{enterpriseId}") + fun registrarSaida(@Path("enterpriseId") idEmpresa: Int): Call + // API de Mongo/WebSocket @GET("chats/empresa/{enterpriseId}") @@ -130,14 +146,20 @@ interface ApiService { @Query("chatId") idChat: Long ): Call> + @PATCH("/chats/marcarComoLida/{chatId}") + fun marcarComoLida(@Path("chatId") chatId: Long): Call + // API de Chatbot -// @POST("iniciar_chat") -// fun iniciarChat(@Body request: IniciarChatRequest): Call -// -// @POST("executar_fluxo") -// fun enviarMensagem(@Body request: ChatRequest): Call -// -// @GET("obter_historico") -// fun obterHistorico(@Query("session_id") sessionId: String): Call + @POST("iniciar_chat") + fun iniciarChat(@Body request: IniciarChatRequest): Call + + @POST("executar_fluxo") + fun enviarMensagem(@Body request: ChatRequest): Call + + @POST("historico_funcionario") + fun obterHistoricoFuncionario(@Body request: Map): Call + + @POST("historico_sessao") + fun obterHistoricoSessao(@Body request: HistoricoSessaoRequest): Call } \ No newline at end of file diff --git a/app/src/main/java/com/example/projetosaveit/api/network/ChatBotClient.kt b/app/src/main/java/com/example/projetosaveit/api/network/ChatBotClient.kt new file mode 100644 index 0000000..427e22c --- /dev/null +++ b/app/src/main/java/com/example/projetosaveit/api/network/ChatBotClient.kt @@ -0,0 +1,26 @@ +package com.example.projetosaveit.api.network + +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import java.util.concurrent.TimeUnit + +object ChatBotClient { + private const val BASE_URL = "http://3.92.141.56:8000" + + val okHttpClient = OkHttpClient.Builder() + .connectTimeout(20, TimeUnit.SECONDS) + .readTimeout(120, TimeUnit.SECONDS) + .writeTimeout(120, TimeUnit.SECONDS) + .build() + + val instance: ApiService by lazy { + val retrofit = Retrofit.Builder() + .baseUrl(BASE_URL) + .client(okHttpClient) + .addConverterFactory(GsonConverterFactory.create()) + .build() + + retrofit.create(ApiService::class.java) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/projetosaveit/api/network/RetrofitClientSql.kt b/app/src/main/java/com/example/projetosaveit/api/network/RetrofitClientSql.kt index 66fc763..01380b4 100644 --- a/app/src/main/java/com/example/projetosaveit/api/network/RetrofitClientSql.kt +++ b/app/src/main/java/com/example/projetosaveit/api/network/RetrofitClientSql.kt @@ -1,13 +1,16 @@ package com.example.projetosaveit.api.network +import com.example.projetosaveit.BuildConfig import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import okhttp3.OkHttpClient object RetrofitClientSql { + const val apiToken = BuildConfig.API_TOKEN + private const val BASE_URL = "https://apisaveit.onrender.com" - private const val API_TOKEN = "essentiasaveit-193812-paoea-oei" + private val API_TOKEN = apiToken ?: "" private val client = OkHttpClient.Builder() .addInterceptor { chain -> diff --git a/app/src/main/java/com/example/projetosaveit/api/repository/ChatRepository.kt b/app/src/main/java/com/example/projetosaveit/api/repository/ChatRepository.kt index c9013ac..f087c0a 100644 --- a/app/src/main/java/com/example/projetosaveit/api/repository/ChatRepository.kt +++ b/app/src/main/java/com/example/projetosaveit/api/repository/ChatRepository.kt @@ -1,6 +1,7 @@ package com.example.projetosaveit.api.repository import com.example.projetosaveit.api.network.RetrofitClientMongo +import com.example.projetosaveit.api.network.RetrofitClientSql import com.example.projetosaveit.model.ChatDTO import retrofit2.Call @@ -20,4 +21,8 @@ class ChatRepository { fun getChatHistorico(idChat: Long): Call> { return RetrofitClientMongo.instance.getChatsHistorico(idChat) } + + fun marcarComoLida(chatId: Long): Call { + return RetrofitClientSql.instance.marcarComoLida(chatId) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/projetosaveit/api/repository/ChatbotRepository.kt b/app/src/main/java/com/example/projetosaveit/api/repository/ChatbotRepository.kt new file mode 100644 index 0000000..6cb8826 --- /dev/null +++ b/app/src/main/java/com/example/projetosaveit/api/repository/ChatbotRepository.kt @@ -0,0 +1,31 @@ +package com.example.projetosaveit.api.repository + +import com.example.projetosaveit.api.network.ChatBotClient +import com.example.projetosaveit.model.ChatRequest +import com.example.projetosaveit.model.ChatResponse +import com.example.projetosaveit.model.HistoricoResponse +import com.example.projetosaveit.model.HistoricoSessaoRequest +import com.example.projetosaveit.model.IniciarChatRequest +import com.example.projetosaveit.model.IniciarChatResponse +import retrofit2.Call +import retrofit2.http.Body + +class ChatbotRepository { + fun iniciarChat(request: IniciarChatRequest): Call { + return ChatBotClient.instance.iniciarChat(request) + } + + fun enviarMensagem(request: ChatRequest): Call { + return ChatBotClient.instance.enviarMensagem(request) + } + + fun obterHistoricoFuncionario(funcionarioId: Int): Call { + val request = mapOf("funcionario_id" to funcionarioId) + return ChatBotClient.instance.obterHistoricoFuncionario(request) + } + + // Histórico de mensagens de uma sessão específica + fun obterHistoricoSessao(request: HistoricoSessaoRequest): Call { + return ChatBotClient.instance.obterHistoricoSessao(request) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/projetosaveit/api/repository/EmpresaRepository.kt b/app/src/main/java/com/example/projetosaveit/api/repository/EmpresaRepository.kt index 30b2de3..402ddc5 100644 --- a/app/src/main/java/com/example/projetosaveit/api/repository/EmpresaRepository.kt +++ b/app/src/main/java/com/example/projetosaveit/api/repository/EmpresaRepository.kt @@ -22,4 +22,16 @@ class EmpresaRepository { fun patchEmpresa(id : Long, updates : Map) : Call { return RetrofitClientSql.instance.patchEmpresaId(id, updates) } + + fun deleteEmpresa(enterpriseId : Long) : Call { + return RetrofitClientSql.instance.deleteEmpresa(enterpriseId) + } + + fun registrarEntrada(idEmpresa: Int): Call { + return RetrofitClientSql.instance.registrarEntrada(idEmpresa) + } + + fun registrarSaida(idEmpresa: Int): Call { + return RetrofitClientSql.instance.registrarSaida(idEmpresa) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/projetosaveit/model/Chatbot.kt b/app/src/main/java/com/example/projetosaveit/model/Chatbot.kt new file mode 100644 index 0000000..c0172b8 --- /dev/null +++ b/app/src/main/java/com/example/projetosaveit/model/Chatbot.kt @@ -0,0 +1,41 @@ +package com.example.projetosaveit.model + +data class IniciarChatRequest( + val empresa_id: Int, + val funcionario_id: Int +) + +data class IniciarChatResponse( + val session_id: String +) + +data class ChatRequest( + val user_input: String, + val empresa_id: Int, + val funcionario_id: Int, + val session_id: String +) + +data class ChatResponse( + val resposta_assistente: String +) + +data class HistoricoSessaoRequest( + val funcionario_id: Int, + val session_id: String +) + +data class HistoricoResponse( + val historico: List = emptyList(), + val sessoes: List = emptyList() +) + +data class MensagemHistorico( + val role: String, + val content: String +) + +data class SessaoHistorico( + val session_id: String, + val data: String? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/example/projetosaveit/ui/AdicionarProduto.kt b/app/src/main/java/com/example/projetosaveit/ui/AdicionarProduto.kt index 171cea0..7b56a33 100644 --- a/app/src/main/java/com/example/projetosaveit/ui/AdicionarProduto.kt +++ b/app/src/main/java/com/example/projetosaveit/ui/AdicionarProduto.kt @@ -354,7 +354,7 @@ class AdicionarProduto : AppCompatActivity() { if (p1.isSuccessful) { Toast.makeText( this@AdicionarProduto, - "Inserido com sucesso. Resultado: " + p1.body(), + "Inserido com sucesso", Toast.LENGTH_SHORT ).show() finish() diff --git a/app/src/main/java/com/example/projetosaveit/ui/Chatbot.kt b/app/src/main/java/com/example/projetosaveit/ui/Chatbot.kt index 174076a..6204060 100644 --- a/app/src/main/java/com/example/projetosaveit/ui/Chatbot.kt +++ b/app/src/main/java/com/example/projetosaveit/ui/Chatbot.kt @@ -1,38 +1,296 @@ -package com.example.projetosaveit.ui +package com.example.projetosaveit.ui.chatbot import android.os.Bundle -import android.widget.ImageButton -import androidx.activity.enableEdgeToEdge +import android.util.Log +import android.widget.EditText +import android.widget.ImageView +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.GravityCompat -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat import androidx.drawerlayout.widget.DrawerLayout +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import com.example.projetosaveit.R +import com.example.projetosaveit.adapter.AdapterChatbot +import com.example.projetosaveit.adapter.AdapterSessoes +import com.example.projetosaveit.adapter.recycleView.MensagemChatbot +import com.example.projetosaveit.adapter.recycleView.TipoMensagemChatbot +import com.example.projetosaveit.api.repository.ChatbotRepository +import com.example.projetosaveit.model.* +import com.example.projetosaveit.util.GetEmpresa +import com.example.projetosaveit.util.GetFuncionario +import com.google.android.material.navigation.NavigationView +import com.google.firebase.auth.FirebaseAuth +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response class Chatbot : AppCompatActivity() { + + private lateinit var rvMensagens: RecyclerView + private lateinit var rvConversasDrawer: RecyclerView + private lateinit var edtMensagem: EditText + private lateinit var btnEnviar: ImageView + private lateinit var btnMenu: ImageView private lateinit var drawerLayout: DrawerLayout + private lateinit var navView: NavigationView + + private lateinit var adapterChat: AdapterChatbot + private lateinit var adapterSessoes: AdapterSessoes + private lateinit var chatbotRepository: ChatbotRepository + + private val listaMensagens = mutableListOf() + private val listaSessoes = mutableListOf() + + private var objAutenticar = FirebaseAuth.getInstance() + private var sessionId: String? = null + private var funcionarioId: Int = 10 + private var empresaId: Int = 1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() setContentView(R.layout.activity_chatbot) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets + + val email = objAutenticar.currentUser?.email.toString() + + findViewById(R.id.btVoltarChatbot).setOnClickListener { + finish() + } + + GetEmpresa.pegarEmailEmpresa(email) { empresa -> + if (empresa != null) { + empresaId = empresa.id.toInt() + funcionarioId = 1 + Log.d("Chatbot", "Empresa ID: $empresaId") + Log.d("Chatbot", "Funcionario ID: $funcionarioId") + + findViewById(R.id.txtBoasVindas).text = "Olá, ${empresa.name}\nComo posso te ajudar hoje?" + + inicializarComponentes() + configurarRecyclerViews() + configurarListeners() + carregarHistoricoSessoes() + val headerView = navView.getHeaderView(0) + headerView.findViewById(R.id.btnNovaConversa)?.setOnClickListener { + novaConversa() + } + } else { + GetFuncionario.pegarEmailFunc(email) { func -> + if (func != null) { + funcionarioId = func.id.toInt() + empresaId = func.enterpriseId.toInt() + Log.d("Chatbot", "Funcionario ID: $funcionarioId") + Log.d("Chatbot", "Empresa ID: $empresaId") + + findViewById(R.id.txtBoasVindas).text = "Olá, ${func.name}\nComo posso te ajudar hoje?" + + inicializarComponentes() + configurarRecyclerViews() + configurarListeners() + carregarHistoricoSessoes() + val headerView = navView.getHeaderView(0) + headerView.findViewById(R.id.btnNovaConversa)?.setOnClickListener { + novaConversa() + } + } else { + Log.e("Chatbot", "Nenhuma empresa ou funcionario encontrado para o email: $email") + } + } + } } + } + private fun inicializarComponentes() { + chatbotRepository = ChatbotRepository() drawerLayout = findViewById(R.id.drawerLayout) + navView = findViewById(R.id.navView) + btnEnviar = findViewById(R.id.enviarMsg2) + edtMensagem = findViewById(R.id.escreverMsg) + rvMensagens = findViewById(R.id.rvMensagens) + btnMenu = findViewById(R.id.btMenu) + } -//ac + private fun configurarRecyclerViews() { + adapterChat = AdapterChatbot(listaMensagens) + rvMensagens.layoutManager = LinearLayoutManager(this) + rvMensagens.adapter = adapterChat + + val headerView = navView.getHeaderView(0) + rvConversasDrawer = headerView.findViewById(R.id.recyclerConversasDrawer) + + adapterSessoes = AdapterSessoes(listaSessoes) { sessao -> + abrirConversa(sessao.sessionId) + } + rvConversasDrawer.layoutManager = LinearLayoutManager(this) + rvConversasDrawer.adapter = adapterSessoes + } + + private fun configurarListeners() { + btnMenu.setOnClickListener { + drawerLayout.openDrawer(navView) + } + + btnEnviar.setOnClickListener { + val msg = edtMensagem.text.toString().trim() + if (msg.isNotEmpty()) { + enviarMensagemComSessao(msg) + edtMensagem.text.clear() + } + } } - override fun onBackPressed() { - if (drawerLayout.isDrawerOpen(GravityCompat.START)) { - drawerLayout.closeDrawer(GravityCompat.START) + private fun enviarMensagemComSessao(msg: String) { + if (sessionId == null) { + val request = IniciarChatRequest( + empresa_id = empresaId, + funcionario_id = funcionarioId + ) + iniciarChat(request, msg) } else { - super.onBackPressed() + enviarMensagem(msg) } } + + private fun iniciarChat(request: IniciarChatRequest, primeiraMsg: String) { + chatbotRepository.iniciarChat(request).enqueue(object : Callback { + override fun onResponse( + call: Call, + response: Response + ) { + if (response.isSuccessful) { + sessionId = response.body()?.session_id + Log.d("Chatbot", "Sessao iniciada: $sessionId") + + val tituloSessao = "Sessao ${listaSessoes.size + 1}" + adapterSessoes.adicionarConversa(tituloSessao, sessionId ?: "") + + enviarMensagem(primeiraMsg) + } else { + Log.e("Chatbot", "Erro iniciar chat: ${response.code()} ${response.errorBody()?.string()}") + } + } + + override fun onFailure(call: Call, t: Throwable) { + Log.e("Chatbot", "Falha ao iniciar chat", t) + } + }) + } + + private fun enviarMensagem(msg: String) { + val sessaoAtual = sessionId ?: return + + adapterChat.adicionarMensagem(MensagemChatbot(msg, TipoMensagemChatbot.USUARIO)) + rvMensagens.smoothScrollToPosition(adapterChat.itemCount - 1) + + val chatRequest = ChatRequest( + user_input = msg, + empresa_id = empresaId, + funcionario_id = funcionarioId, + session_id = sessaoAtual + ) + + chatbotRepository.enviarMensagem(chatRequest).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful) { + val resposta = response.body()?.resposta_assistente ?: "(sem resposta)" + adapterChat.adicionarMensagem(MensagemChatbot(resposta, TipoMensagemChatbot.BOT)) + rvMensagens.smoothScrollToPosition(adapterChat.itemCount - 1) + } else { + Log.e("Chatbot", "Erro enviar mensagem: ${response.code()} ${response.errorBody()?.string()}") + } + } + + override fun onFailure(call: Call, t: Throwable) { + Log.e("Chatbot", "Falha ao enviar mensagem", t) + } + }) + } + + private fun carregarHistoricoSessoes() { + Log.d("Chatbot", "Carregando historico de SESSOES...") + + chatbotRepository.obterHistoricoFuncionario(funcionarioId).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful) { + val sessoes = response.body()?.sessoes ?: emptyList() + listaSessoes.clear() + + Log.d("Chatbot", "${sessoes.size} sessoes carregadas") + + sessoes.forEachIndexed { index, sessao -> + val titulo = "Conversa ${index + 1} - ${sessao.data?.substring(0, 10) ?: "Data"}" + listaSessoes.add(com.example.projetosaveit.adapter.ConversaItem(titulo, sessao.session_id)) + } + + adapterSessoes.notifyDataSetChanged() + + if (sessoes.isNotEmpty()) { + sessionId = sessoes.first().session_id + carregarHistoricoMensagens(sessoes.first().session_id) + } + + } else { + Log.e("Chatbot", "Erro carregar historico de SESSOES: ${response.code()}") + } + } + + override fun onFailure(call: Call, t: Throwable) { + Log.e("Chatbot", "Falha ao carregar historico de SESSOES", t) + } + }) + } + + private fun carregarHistoricoMensagens(sessionId: String) { + Log.d("Chatbot", "Carregando historico de MENSAGENS da sessao: $sessionId") + + val request = HistoricoSessaoRequest( + funcionario_id = funcionarioId, + session_id = sessionId + ) + + chatbotRepository.obterHistoricoSessao(request).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful) { + val historico = response.body()?.historico ?: emptyList() + listaMensagens.clear() + + Log.d("Chatbot", "${historico.size} mensagens carregadas") + + historico.forEach { mensagem -> + val tipo = when (mensagem.role) { + "user" -> TipoMensagemChatbot.USUARIO + "assistant" -> TipoMensagemChatbot.BOT + else -> TipoMensagemChatbot.BOT + } + listaMensagens.add(MensagemChatbot(mensagem.content, tipo)) + } + + adapterChat.notifyDataSetChanged() + if (listaMensagens.isNotEmpty()) { + rvMensagens.scrollToPosition(listaMensagens.size - 1) + } + + } else { + Log.e("Chatbot", "Erro carregar historico de MENSAGENS: ${response.code()}") + } + } + + override fun onFailure(call: Call, t: Throwable) { + Log.e("Chatbot", "Falha ao carregar historico de MENSAGENS", t) + } + }) + } + + private fun abrirConversa(sessionSelecionada: String) { + Log.d("Chatbot", "Abrindo conversa: $sessionSelecionada") + sessionId = sessionSelecionada + carregarHistoricoMensagens(sessionSelecionada) + drawerLayout.closeDrawers() + } + + fun novaConversa() { + sessionId = null + listaMensagens.clear() + adapterChat.notifyDataSetChanged() + drawerLayout.closeDrawers() + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/projetosaveit/ui/ConfiguracoesPerfil.kt b/app/src/main/java/com/example/projetosaveit/ui/ConfiguracoesPerfil.kt index 92bb5ab..7deab95 100644 --- a/app/src/main/java/com/example/projetosaveit/ui/ConfiguracoesPerfil.kt +++ b/app/src/main/java/com/example/projetosaveit/ui/ConfiguracoesPerfil.kt @@ -2,23 +2,33 @@ package com.example.projetosaveit.ui import android.content.Intent import android.os.Bundle +import android.util.Log import android.widget.Button import android.widget.FrameLayout import android.widget.ImageView import android.widget.TextView +import android.widget.Toast import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import com.example.projetosaveit.ui.AtualizarNome import com.example.projetosaveit.R +import com.example.projetosaveit.api.repository.EmpresaRepository +import com.example.projetosaveit.ui.AdicionarProduto import com.example.projetosaveit.util.GetEmpresa import com.example.projetosaveit.util.GetFuncionario import com.google.firebase.auth.FirebaseAuth +import okhttp3.ResponseBody +import retrofit2.Call +import retrofit2.Response class ConfiguracoesPerfil : AppCompatActivity() { val objAutenticar: FirebaseAuth = FirebaseAuth.getInstance() + var idEmpresa : Long = 0 + val repository : EmpresaRepository = EmpresaRepository() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -33,10 +43,12 @@ class ConfiguracoesPerfil : AppCompatActivity() { GetEmpresa.pegarEmailEmpresa(email) { empresa -> if (empresa != null) { + idEmpresa = empresa.id (findViewById(R.id.emailUsuarioTxt)).text = empresa.email } else { GetFuncionario.pegarEmailFunc(email) { func -> if (func != null) { + idEmpresa = func.id GetEmpresa.pegarIdEmpresa(func.enterpriseId) { empresa -> if (empresa != null) { (findViewById(R.id.emailUsuarioTxt)).text = (empresa.email) @@ -51,6 +63,18 @@ class ConfiguracoesPerfil : AppCompatActivity() { } } + (findViewById