chatbot update
parent
3fb481f1f9
commit
85e3530e9a
|
@ -0,0 +1,61 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class ApiProxyController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly HttpClient _httpClient;
|
||||||
|
|
||||||
|
private const string N8nWebhookUrl = "https://n8n.nurarif.in/webhook/f2129606-7716-415b-a83b-b9c0e84b752f/chat";
|
||||||
|
|
||||||
|
public ApiProxyController(IHttpClientFactory httpClientFactory)
|
||||||
|
{
|
||||||
|
_httpClient = httpClientFactory.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("chatbot")]
|
||||||
|
public async Task<IActionResult> Chatbot([FromBody] ChatRequest request)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var payload = new { message = request.Message };
|
||||||
|
var json = JsonSerializer.Serialize(payload);
|
||||||
|
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
var response = await _httpClient.PostAsync(N8nWebhookUrl, content);
|
||||||
|
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
return StatusCode((int)response.StatusCode, new { code = (int)response.StatusCode, message = "Webhook error: " + await response.Content.ReadAsStringAsync() });
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Try to parse response as JSON
|
||||||
|
var parsed = JsonSerializer.Deserialize<Dictionary<string, string>>(result);
|
||||||
|
return Ok(parsed);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// If not JSON, return as plain text
|
||||||
|
return Ok(new { reply = result });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return StatusCode(500, new { message = "Internal server error", error = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ChatRequest
|
||||||
|
{
|
||||||
|
public string Message { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ builder.Services.AddControllersWithViews();
|
||||||
|
|
||||||
|
|
||||||
builder.Services.AddLucideIcons();
|
builder.Services.AddLucideIcons();
|
||||||
|
builder.Services.AddHttpClient(); // Tambahkan ini sebelum builder.Build()
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
|
|
@ -67,9 +67,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-orange-100 text-orange-800 border border-orange-200 mb-4 gap-2">
|
<div class="flex">
|
||||||
<i class="w-4 h-4 text-green-600" data-lucide="book-open-text"></i>
|
<div class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-orange-100 text-orange-800 border border-orange-200 mb-4 gap-2">
|
||||||
<h2 id="kategoriLabel" class="text-sm font-semibold">Pengelolaan Limbah B3</h2>
|
<i class="w-4 h-4 text-green-600" data-lucide="book-open-text"></i>
|
||||||
|
<span id="kategoriLabel" class="text-sm font-semibold">Pengelolaan Limbah B3</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="dokumenGrid" class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
<div id="dokumenGrid" class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||||
<!-- Daftar dokumen default -->
|
<!-- Daftar dokumen default -->
|
||||||
|
@ -134,29 +136,34 @@
|
||||||
<script src="~/assets/dflip/js/libs/jquery.min.js" type="text/javascript"></script>
|
<script src="~/assets/dflip/js/libs/jquery.min.js" type="text/javascript"></script>
|
||||||
<script src="~/assets/dflip/js/dflip.min.js" type="text/javascript"></script>
|
<script src="~/assets/dflip/js/dflip.min.js" type="text/javascript"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
// Ambil URL dari Razor agar bisa dipakai di JS
|
||||||
|
// HARDCODE hasil Razor ke dalam string agar tidak error interpretasi JS
|
||||||
|
const pdfUrl = "@Url.Content("~/assets/documents/dikplhd/Buku_1_Ringkasan_Eksekutif_DIKPLHD_2019.pdf")";
|
||||||
|
const imgUrl = "@Url.Content("~/assets/images/dikplhd/buku.jpg")";
|
||||||
|
|
||||||
const dokumenHTML = {
|
const dokumenHTML = {
|
||||||
"Pengelolaan Limbah B3": `
|
"Pengelolaan Limbah B3": `
|
||||||
<div class="bg-white rounded-xl shadow-sm">
|
<div class="bg-white rounded-xl shadow-sm">
|
||||||
<div class="relative overflow-hidden rounded-lg">
|
<div class="relative overflow-hidden rounded-lg">
|
||||||
<div class="_df_thumb" source="@Url.Content("~/assets/documents/dikplhd/Buku_1_Ringkasan_Eksekutif_DIKPLHD_2019.pdf")" thumb="@Url.Content("~/assets/images/dikplhd/buku.jpg")">Klik untuk Lihat & Unduh</div>
|
<div class="_df_thumb" source="${pdfUrl}" thumb="${imgUrl}">Klik untuk Lihat & Unduh</div>
|
||||||
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Buku I Ringkasan Eksekutif DIKPLHD Tahun 2019</h3>
|
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Buku I Ringkasan Eksekutif DIKPLHD Tahun 2019</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-white rounded-xl shadow-sm">
|
<div class="bg-white rounded-xl shadow-sm">
|
||||||
<div class="relative overflow-hidden rounded-lg">
|
<div class="relative overflow-hidden rounded-lg">
|
||||||
<div class="_df_thumb" source="@Url.Content("~/assets/documents/dikplhd/Buku_1_Ringkasan_Eksekutif_DIKPLHD_2019.pdf")" thumb="@Url.Content("~/assets/images/dikplhd/buku.jpg")">Klik untuk Lihat & Unduh</div>
|
<div class="_df_thumb" source="${pdfUrl}" thumb="${imgUrl}">Klik untuk Lihat & Unduh</div>
|
||||||
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Buku I Ringkasan Eksekutif DIKPLHD Tahun 2019</h3>
|
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Buku I Ringkasan Eksekutif DIKPLHD Tahun 2019</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-white rounded-xl shadow-sm">
|
<div class="bg-white rounded-xl shadow-sm">
|
||||||
<div class="relative overflow-hidden rounded-lg">
|
<div class="relative overflow-hidden rounded-lg">
|
||||||
<div class="_df_thumb" source="@Url.Content("~/assets/documents/dikplhd/Buku_1_Ringkasan_Eksekutif_DIKPLHD_2019.pdf")" thumb="@Url.Content("~/assets/images/dikplhd/buku.jpg")">Klik untuk Lihat & Unduh</div>
|
<div class="_df_thumb" source="${pdfUrl}" thumb="${imgUrl}">Klik untuk Lihat & Unduh</div>
|
||||||
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Buku I Ringkasan Eksekutif DIKPLHD Tahun 2019</h3>
|
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Buku I Ringkasan Eksekutif DIKPLHD Tahun 2019</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-white rounded-xl shadow-sm">
|
<div class="bg-white rounded-xl shadow-sm">
|
||||||
<div class="relative overflow-hidden rounded-lg">
|
<div class="relative overflow-hidden rounded-lg">
|
||||||
<div class="_df_thumb" source="@Url.Content("~/assets/documents/dikplhd/Buku_1_Ringkasan_Eksekutif_DIKPLHD_2019.pdf")" thumb="@Url.Content("~/assets/images/dikplhd/buku.jpg")">Klik untuk Lihat & Unduh</div>
|
<div class="_df_thumb" source="${pdfUrl}" thumb="${imgUrl}">Klik untuk Lihat & Unduh</div>
|
||||||
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Buku I Ringkasan Eksekutif DIKPLHD Tahun 2019</h3>
|
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Buku I Ringkasan Eksekutif DIKPLHD Tahun 2019</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -164,7 +171,7 @@
|
||||||
"Pengendalian Pencemaran Air": `
|
"Pengendalian Pencemaran Air": `
|
||||||
<div class="bg-white rounded-xl shadow-sm">
|
<div class="bg-white rounded-xl shadow-sm">
|
||||||
<div class="relative overflow-hidden rounded-lg">
|
<div class="relative overflow-hidden rounded-lg">
|
||||||
<div class="_df_thumb" source="@Url.Content("~/assets/documents/dikplhd/Buku_1_Ringkasan_Eksekutif_DIKPLHD_2019.pdf")" thumb="@Url.Content("~/assets/images/dikplhd/buku.jpg")">Klik untuk Lihat & Unduh</div>
|
<div class="_df_thumb" source="${pdfUrl}" thumb="${imgUrl}">Klik untuk Lihat & Unduh</div>
|
||||||
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Panduan Pengendalian Pencemaran Air 2023</h3>
|
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Panduan Pengendalian Pencemaran Air 2023</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -172,7 +179,7 @@
|
||||||
"Pengendalian Pencemaran Udara": `
|
"Pengendalian Pencemaran Udara": `
|
||||||
<div class="bg-white rounded-xl shadow-sm">
|
<div class="bg-white rounded-xl shadow-sm">
|
||||||
<div class="relative overflow-hidden rounded-lg">
|
<div class="relative overflow-hidden rounded-lg">
|
||||||
<div class="_df_thumb" source="@Url.Content("~/assets/documents/dikplhd/Buku_1_Ringkasan_Eksekutif_DIKPLHD_2019.pdf")" thumb="@Url.Content("~/assets/images/dikplhd/buku.jpg")">Klik untuk Lihat & Unduh</div>
|
<div class="_df_thumb" source="${pdfUrl}" thumb="${imgUrl}">Klik untuk Lihat & Unduh</div>
|
||||||
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Pedoman Pengendalian Udara Bersih 2024</h3>
|
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Pedoman Pengendalian Udara Bersih 2024</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -180,7 +187,7 @@
|
||||||
"Pengelolaan Limbah Padat": `
|
"Pengelolaan Limbah Padat": `
|
||||||
<div class="bg-white rounded-xl shadow-sm">
|
<div class="bg-white rounded-xl shadow-sm">
|
||||||
<div class="relative overflow-hidden rounded-lg">
|
<div class="relative overflow-hidden rounded-lg">
|
||||||
<div class="_df_thumb" source="@Url.Content("~/assets/documents/dikplhd/Buku_1_Ringkasan_Eksekutif_DIKPLHD_2019.pdf")" thumb="@Url.Content("~/assets/images/dikplhd/buku.jpg")">Klik untuk Lihat & Unduh</div>
|
<div class="_df_thumb" source="${pdfUrl}" thumb="${imgUrl}">Klik untuk Lihat & Unduh</div>
|
||||||
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Standar Teknis Pengelolaan Limbah Padat</h3>
|
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Standar Teknis Pengelolaan Limbah Padat</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -188,7 +195,7 @@
|
||||||
"Peraturan dan Pedoman Terkait...": `
|
"Peraturan dan Pedoman Terkait...": `
|
||||||
<div class="bg-white rounded-xl shadow-sm">
|
<div class="bg-white rounded-xl shadow-sm">
|
||||||
<div class="relative overflow-hidden rounded-lg">
|
<div class="relative overflow-hidden rounded-lg">
|
||||||
<div class="_df_thumb" source="@Url.Content("~/assets/documents/dikplhd/Buku_1_Ringkasan_Eksekutif_DIKPLHD_2019.pdf")" thumb="@Url.Content("~/assets/images/dikplhd/buku.jpg")">Klik untuk Lihat & Unduh</div>
|
<div class="_df_thumb" source="${pdfUrl}" thumb="${imgUrl}">Klik untuk Lihat & Unduh</div>
|
||||||
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Peraturan Pengendalian Dampak Perubahan Iklim</h3>
|
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Peraturan Pengendalian Dampak Perubahan Iklim</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -196,7 +203,7 @@
|
||||||
"Peraturan Gubernur Jakarta Sadar...": `
|
"Peraturan Gubernur Jakarta Sadar...": `
|
||||||
<div class="bg-white rounded-xl shadow-sm">
|
<div class="bg-white rounded-xl shadow-sm">
|
||||||
<div class="relative overflow-hidden rounded-lg">
|
<div class="relative overflow-hidden rounded-lg">
|
||||||
<div class="_df_thumb" source="@Url.Content("~/assets/documents/dikplhd/Buku_1_Ringkasan_Eksekutif_DIKPLHD_2019.pdf")" thumb="@Url.Content("~/assets/images/dikplhd/buku.jpg")">Klik untuk Lihat & Unduh</div>
|
<div class="_df_thumb" source="${pdfUrl}" thumb="${imgUrl}">Klik untuk Lihat & Unduh</div>
|
||||||
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Peraturan Gubernur Jakarta Sadar Sampah</h3>
|
<h3 class="text-xs font-bold mb-3 text-gray-800 group-hover:text-green-600 transition-colors px-4">Peraturan Gubernur Jakarta Sadar Sampah</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -211,11 +218,19 @@
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set kategori dari localStorage jika ada
|
||||||
|
const savedKategori = localStorage.getItem('selectedKategori');
|
||||||
|
if (savedKategori) {
|
||||||
|
$('#kategoriSelect').val(savedKategori);
|
||||||
|
$('#kategoriLabel').text(savedKategori);
|
||||||
|
$('#dokumenGrid').html(dokumenHTML[getSelectedKategori()] || '');
|
||||||
|
}
|
||||||
|
@*
|
||||||
$('#kategoriSelect').on('change', function() {
|
$('#kategoriSelect').on('change', function() {
|
||||||
const kategori = getSelectedKategori();
|
const selected = $(this).val();
|
||||||
$('#kategoriLabel').text($(this).find('option:selected').text());
|
localStorage.setItem('selectedKategori', selected);
|
||||||
$('#dokumenGrid').html(dokumenHTML[kategori] || '');
|
location.reload();
|
||||||
});
|
}); *@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</register-block>
|
</register-block>
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
<footer class="bg-oren pt-8">
|
<footer class="bg-oren pt-8">
|
||||||
<!-- Main Footer Section -->
|
<!-- Main Footer Section -->
|
||||||
<div class="relative max-w-6xl bg-ijo rounded-2xl mx-auto overflow-hidden shadow-2xl">
|
<div class="relative max-w-6xl bg-ijo rounded-2xl mx-auto overflow-hidden shadow-2xl">
|
||||||
|
@ -135,6 +134,34 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Chat Button -->
|
||||||
|
<div id="chatButton" class="fixed bottom-5 right-5 p-4 rounded-full cursor-pointer z-50">
|
||||||
|
<img src="@Url.Content("~/chatbot.gif")" alt="Chat Icon" class="w-12 h-12 rounded-full"/>
|
||||||
|
<div class="absolute -top-8 -left-3 bg-green-500 text-white text-xs px-2 py-1 rounded whitespace-nowrap">
|
||||||
|
Tanya saya!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Chatbot -->
|
||||||
|
<div id="chatbot" class="fixed bottom-20 right-5 w-80 h-96 bg-white rounded-lg shadow-xl transform transition-all duration-300 scale-0 z-50">
|
||||||
|
<div class="flex justify-between items-center bg-blue-600 text-white p-4 rounded-t-lg">
|
||||||
|
<h3 class="font-semibold text-lg flex items-center">
|
||||||
|
<i class="text-yellow-300 w-6 h-6 lg:w-8 lg:h-8 mr-2" data-lucide="bot-message-square"></i>EcoBot</h3>
|
||||||
|
<button id="closeChat" class="text-white font-bold text-xl">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="chat-content p-4 h-72 overflow-y-auto bg-gray-50 rounded-b-lg">
|
||||||
|
<div class="chat-bubble bot" style="float: left; clear: both;">
|
||||||
|
<p>Halo! Selamat datang di layanan informasi Dinas Lingkungan Hidup DKI Jakarta! 👋</p>
|
||||||
|
<p>Saya di sini untuk membantu Anda. Ada yang ingin ditanyakan seputar layanan kami?</p>
|
||||||
|
</div>
|
||||||
|
<!-- Chat messages will appear here -->
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center p-4 bg-green-100 border-t border-gray-300 rounded-b-lg">
|
||||||
|
<input type="text" id="userInput" placeholder="Type a message..." class="w-full p-2 rounded-lg border border-gray-300" />
|
||||||
|
<button id="sendMessage" class="ml-2 p-2 bg-green-600 text-white rounded-lg">Send</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -170,6 +197,157 @@ a.flip-animate.flipped span {
|
||||||
a.flip-animate.flipped span:before {
|
a.flip-animate.flipped span:before {
|
||||||
color: #fbbf24;
|
color: #fbbf24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-content {
|
||||||
|
background: linear-gradient(135deg, #e6f9e6 0%, #e0f7fa 100%);
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
padding: 1rem;
|
||||||
|
min-height: 200px;
|
||||||
|
font-size: 1rem;
|
||||||
|
box-shadow: 0 2px 8px 0 #22c55e33;
|
||||||
|
}
|
||||||
|
.chat-bubble {
|
||||||
|
display: block;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
border-radius: 1.2em;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
max-width: 80%;
|
||||||
|
word-break: break-word;
|
||||||
|
box-shadow: 0 1px 4px 0 #22c55e22;
|
||||||
|
position: relative;
|
||||||
|
font-size: 0.98rem;
|
||||||
|
transition: background 0.2s;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
.chat-bubble.user {
|
||||||
|
background: linear-gradient(135deg, #bbf7d0 0%, #4ade80 100%);
|
||||||
|
color: #134e1c;
|
||||||
|
float: right;
|
||||||
|
border-bottom-right-radius: 0.3em;
|
||||||
|
border: 1.5px solid #22c55e;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 10pt;
|
||||||
|
}
|
||||||
|
.chat-bubble.bot {
|
||||||
|
background: linear-gradient(135deg, #fff 0%, #d1fae5 100%);
|
||||||
|
color: #134e1c;
|
||||||
|
float: left;
|
||||||
|
border-bottom-left-radius: 0.3em;
|
||||||
|
border: 1.5px solid #22c55e;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 10pt;
|
||||||
|
}
|
||||||
|
.chat-bubble.time {
|
||||||
|
background: transparent;
|
||||||
|
color: #888;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
box-shadow: none;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0.5rem auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.chat-content p {
|
||||||
|
margin: 0.2rem 0;
|
||||||
|
}
|
||||||
|
.chat-bubble.user:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
right: -10px;
|
||||||
|
bottom: 0;
|
||||||
|
width: 16px;
|
||||||
|
height: 20px;
|
||||||
|
background: transparent;
|
||||||
|
background-image: radial-gradient(circle at 0 0, #4ade80 60%, transparent 61%);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.chat-bubble.bot:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
bottom: 0;
|
||||||
|
width: 16px;
|
||||||
|
height: 20px;
|
||||||
|
background: transparent;
|
||||||
|
background-image: radial-gradient(circle at 100% 0, #d1fae5 60%, transparent 61%);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
#chatbot .bg-blue-600 {
|
||||||
|
background: linear-gradient(90deg, #22c55e 0%, #4ade80 100%) !important;
|
||||||
|
}
|
||||||
|
#chatbot h3 {
|
||||||
|
color: #fff;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
#chatbot button#closeChat {
|
||||||
|
color: #fff;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
#chatbot button#closeChat:hover {
|
||||||
|
color: #22c55e;
|
||||||
|
}
|
||||||
|
#chatbot input[type="text"] {
|
||||||
|
border: 1.5px solid #22c55e;
|
||||||
|
background: #f0fdf4;
|
||||||
|
}
|
||||||
|
#chatbot button#sendMessage {
|
||||||
|
background: linear-gradient(90deg, #22c55e 0%, #4ade80 100%);
|
||||||
|
color: #fff;
|
||||||
|
font-weight: bold;
|
||||||
|
border: none;
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
|
#chatbot button#sendMessage:hover {
|
||||||
|
background: linear-gradient(90deg, #4ade80 0%, #22c55e 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Typing indicator animation */
|
||||||
|
.typing-indicator {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
background: linear-gradient(135deg, #fff 0%, #d1fae5 100%);
|
||||||
|
border: 1.5px solid #22c55e;
|
||||||
|
border-radius: 1.2em;
|
||||||
|
border-bottom-left-radius: 0.3em;
|
||||||
|
float: left;
|
||||||
|
clear: both;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
max-width: 80%;
|
||||||
|
box-shadow: 0 1px 4px 0 #22c55e22;
|
||||||
|
}
|
||||||
|
.typing-indicator span {
|
||||||
|
height: 8px;
|
||||||
|
width: 8px;
|
||||||
|
float: left;
|
||||||
|
margin: 0 1px;
|
||||||
|
background-color: #22c55e;
|
||||||
|
display: block;
|
||||||
|
border-radius: 50%;
|
||||||
|
opacity: 0.4;
|
||||||
|
animation: typing 1.4s infinite ease-in-out both;
|
||||||
|
}
|
||||||
|
.typing-indicator span:nth-child(1) { animation-delay: -0.32s; }
|
||||||
|
.typing-indicator span:nth-child(2) { animation-delay: -0.16s; }
|
||||||
|
.typing-indicator span:nth-child(3) { animation-delay: 0s; }
|
||||||
|
@@keyframes typing {
|
||||||
|
0%, 80%, 100% {
|
||||||
|
transform: scale(0);
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.typing-text {
|
||||||
|
margin-left: 8px;
|
||||||
|
color: #22c55e;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -183,3 +361,117 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const chatButton = document.getElementById("chatButton");
|
||||||
|
const chatbot = document.getElementById("chatbot");
|
||||||
|
const closeChat = document.getElementById("closeChat");
|
||||||
|
const sendMessage = document.getElementById("sendMessage");
|
||||||
|
const userInput = document.getElementById("userInput");
|
||||||
|
|
||||||
|
chatButton.addEventListener("click", () => {
|
||||||
|
chatbot.classList.remove('scale-0');
|
||||||
|
chatbot.classList.add('scale-100');
|
||||||
|
});
|
||||||
|
|
||||||
|
closeChat.addEventListener("click", () => {
|
||||||
|
chatbot.classList.remove('scale-100');
|
||||||
|
chatbot.classList.add('scale-0');
|
||||||
|
});
|
||||||
|
|
||||||
|
sendMessage.addEventListener("click", sendChatMessage);
|
||||||
|
userInput.addEventListener("keydown", function(e) {
|
||||||
|
if (e.key === "Enter") sendChatMessage();
|
||||||
|
});
|
||||||
|
|
||||||
|
function sendChatMessage() {
|
||||||
|
const chatContent = document.querySelector(".chat-content");
|
||||||
|
const message = userInput.value.trim();
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
// User bubble (kanan)
|
||||||
|
const userBubble = document.createElement("div");
|
||||||
|
userBubble.className = "chat-bubble user";
|
||||||
|
userBubble.style.cssFloat = "right";
|
||||||
|
userBubble.style.clear = "both";
|
||||||
|
userBubble.textContent = message;
|
||||||
|
chatContent.appendChild(userBubble);
|
||||||
|
chatContent.scrollTop = chatContent.scrollHeight;
|
||||||
|
|
||||||
|
userInput.value = '';
|
||||||
|
|
||||||
|
// Show typing indicator
|
||||||
|
const typingIndicator = document.createElement("div");
|
||||||
|
typingIndicator.className = "typing-indicator";
|
||||||
|
typingIndicator.innerHTML = `
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
@* <span class="typing-text">EcoBot sedang mengetik...</span> *@
|
||||||
|
`;
|
||||||
|
chatContent.appendChild(typingIndicator);
|
||||||
|
chatContent.scrollTop = chatContent.scrollHeight;
|
||||||
|
|
||||||
|
fetch('/api/apiproxy/chatbot', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
message: message
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
return response.json().catch(() => response.text());
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
// Remove typing indicator
|
||||||
|
typingIndicator.remove();
|
||||||
|
|
||||||
|
let reply = "";
|
||||||
|
if (data && typeof data === "object" && data.code === 404 && data.message && data.message.includes("webhook")) {
|
||||||
|
reply = "Bot sedang offline. Silakan klik 'Execute workflow' di n8n, lalu coba lagi.";
|
||||||
|
} else if (typeof data === "string") {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(data);
|
||||||
|
reply = parsed.output || parsed.reply || parsed.message || parsed.text || "";
|
||||||
|
} catch {
|
||||||
|
reply = data;
|
||||||
|
}
|
||||||
|
} else if (typeof data === "object" && data !== null) {
|
||||||
|
reply = data.output || data.reply || data.message || data.text || "";
|
||||||
|
}
|
||||||
|
if (!reply) reply = "Maaf, saya tidak mengerti.";
|
||||||
|
|
||||||
|
// Format reply: convert **text** to bold and handle line breaks
|
||||||
|
reply = reply.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>').replace(/\n/g, "<br>");
|
||||||
|
reply = reply.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>').replace(/\*(.*?)\*/g, '<em>$1</em>').replace(/\n/g, "<br>");
|
||||||
|
|
||||||
|
// Bot bubble (kiri)
|
||||||
|
const botBubble = document.createElement("div");
|
||||||
|
botBubble.className = "chat-bubble bot";
|
||||||
|
botBubble.style.cssFloat = "left";
|
||||||
|
botBubble.style.clear = "both";
|
||||||
|
botBubble.innerHTML = reply;
|
||||||
|
chatContent.appendChild(botBubble);
|
||||||
|
chatContent.scrollTop = chatContent.scrollHeight;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
// Remove typing indicator
|
||||||
|
typingIndicator.remove();
|
||||||
|
|
||||||
|
const botBubble = document.createElement("div");
|
||||||
|
botBubble.className = "chat-bubble bot";
|
||||||
|
botBubble.style.cssFloat = "left";
|
||||||
|
botBubble.style.clear = "both";
|
||||||
|
botBubble.textContent = "Maaf, terjadi kesalahan koneksi.";
|
||||||
|
chatContent.appendChild(botBubble);
|
||||||
|
chatContent.scrollTop = chatContent.scrollHeight;
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -13,7 +13,7 @@ using System.Reflection;
|
||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("dlh-net")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("dlh-net")]
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+10008e794cfb8ed52220417cc2c874b021093ecf")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3fb481f1f9f26ba2171aabc0fdb596b6923e30dc")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("dlh-net")]
|
[assembly: System.Reflection.AssemblyProductAttribute("dlh-net")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("dlh-net")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("dlh-net")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
51b0091c9bc9d5bebf036f8de5b6eb8bb5b5edf5ccfc420cda8bb0b19348bdc5
|
8b309c95af47ccef6d2a4591f3aa7b0fe15558ba0030b407144540a73245cb26
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
50797de467140eb544248ad24754b93b6bbfc6bde36940d84d2d2717837bbfd1
|
d8ee9c319eb7da9aa59b63c89dba6210232db42fcca4f56b121621ced6e95543
|
||||||
|
|
|
@ -6440,4 +6440,5 @@ C:\laragon\www\dlh-net\obj\Debug\net9.0\rpswa.dswa.cache.json
|
||||||
C:\laragon\www\dlh-net\obj\Debug\net9.0\rjimswa.dswa.cache.json
|
C:\laragon\www\dlh-net\obj\Debug\net9.0\rjimswa.dswa.cache.json
|
||||||
C:\laragon\www\dlh-net\obj\Debug\net9.0\rjsmrazor.dswa.cache.json
|
C:\laragon\www\dlh-net\obj\Debug\net9.0\rjsmrazor.dswa.cache.json
|
||||||
C:\laragon\www\dlh-net\obj\Debug\net9.0\rjsmcshtml.dswa.cache.json
|
C:\laragon\www\dlh-net\obj\Debug\net9.0\rjsmcshtml.dswa.cache.json
|
||||||
C:\laragon\www\dlh-net\obj\Debug\net9.0\compressed\hc40dw3fux-nv0eo9yu5k.gz
|
C:\laragon\www\dlh-net\obj\Debug\net9.0\compressed\s9158qcgwh-r8za1puz0v.gz
|
||||||
|
C:\laragon\www\dlh-net\obj\Debug\net9.0\compressed\hc40dw3fux-bsf4q98k6j.gz
|
||||||
|
|
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
wuXlcKp3N92JQemfnMaWSpCyP7qlCJaEMpFSJrLDJo0=
|
Djyed7vo8rvxJS67tD6vxwI6uV46EF2UviSbLnoRQTc=
|
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 2.0 MiB |
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue