From c1a9f378887eb34e904778b14ce84197c2248f14 Mon Sep 17 00:00:00 2001 From: Vassshhh Date: Thu, 7 Aug 2025 00:10:38 +0700 Subject: [PATCH] ok --- src/ChatBot.js | 100 ++++++++++++--------------------- src/Dashboard.js | 5 +- src/DiscussedTopics.js | 62 +++++++++++++++----- src/DiscussedTopics.module.css | 33 ++++++++++- 4 files changed, 119 insertions(+), 81 deletions(-) diff --git a/src/ChatBot.js b/src/ChatBot.js index ec095bc..70f84ed 100644 --- a/src/ChatBot.js +++ b/src/ChatBot.js @@ -9,17 +9,13 @@ const ChatBot = ({ existingConversation }) => { sender: 'bot', text: 'Hai! Saya Alle, asisten virtual Dermalounge Clinic. Ada yang bisa Alle bantu hari ini?', time: getTime(), - quickReplies: [ - 'Konsultasi Estetik', - 'Konsultasi Kulit & Kelamin' - ], + quickReplies: ['Konsultasi Estetik', 'Konsultasi Kulit & Kelamin'], }, ]); const [searchParams, setSearchParams] = useSearchParams(); -const navigate = useNavigate(); - -const isOpenCamera = searchParams.get('camera') === 'open'; + const navigate = useNavigate(); + const isOpenCamera = searchParams.get('camera') === 'open'; const [input, setInput] = useState(''); const [isLoading, setIsLoading] = useState(''); @@ -45,8 +41,7 @@ const isOpenCamera = searchParams.get('camera') === 'open'; const sessionId = generateUUID(); const dateNow = new Date().toISOString(); - - sessionStorage.setItem('session', JSON.stringify({ sessionId: sessionId, lastSeen: dateNow })) + sessionStorage.setItem('session', JSON.stringify({ sessionId, lastSeen: dateNow })); } }, []); @@ -56,11 +51,9 @@ const isOpenCamera = searchParams.get('camera') === 'open'; const bstr = atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n); - while (n--) { u8arr[n] = bstr.charCodeAt(n); } - return new File([u8arr], filename, { type: mime }); } @@ -70,7 +63,6 @@ const isOpenCamera = searchParams.get('camera') === 'open'; let body; let headers; - const isBase64Image = type === 'image' && typeof content === 'string' && content.startsWith('data:image/'); if (isBase64Image) { @@ -82,7 +74,6 @@ const isOpenCamera = searchParams.get('camera') === 'open'; formData.append('phoneNumber', session.phoneNumber || ''); formData.append('type', type); formData.append('image', file); - body = formData; headers = {}; } else { @@ -103,7 +94,6 @@ const isOpenCamera = searchParams.get('camera') === 'open'; headers, body, }); - const data = await response.json(); return data; } catch (error) { @@ -119,7 +109,14 @@ const isOpenCamera = searchParams.get('camera') === 'open'; }; const handleUploadImage = async (img) => { - setSearchParams({ }) + const session = JSON.parse(sessionStorage.getItem('session')); + if (!session?.name || !session?.phoneNumber) { + setIsPoppedUp(img); // simpan gambar untuk dikirim setelah user isi data + setSearchParams({}); + return; + } + + setSearchParams({}); const newMessages = [ ...messages, { sender: 'user', img: img, time: getTime() }, @@ -128,14 +125,12 @@ const isOpenCamera = searchParams.get('camera') === 'open'; setIsLoading('Menganalisa gambar anda...'); const data = await askToBot({ type: 'image', content: img }); - const botAnswer = data.jawaban || 'Maaf, saya tidak bisa menganalisis gambar tersebut.'; setMessages((prev) => [ ...prev, { sender: 'bot', text: botAnswer, time: getTime() }, ]); - setIsLoading(''); }; @@ -150,25 +145,19 @@ const isOpenCamera = searchParams.get('camera') === 'open'; return; } - const newMessages = [ - ...messages, - { sender: 'user', text: message, time: getTime() }, - ]; - + const newMessages = [...messages, { sender: 'user', text: message, time: getTime() }]; setMessages(newMessages); setInput(''); setIsLoading('Mengetik...'); try { const data = await askToBot({ type: 'text', content: message, tryCount }); - const botAnswer = data.jawaban || 'Maaf saya sedang tidak tersedia sekarang, coba lagi nanti'; setMessages(prev => [ ...prev, { sender: 'bot', text: botAnswer, time: getTime() }, ]); - setIsLoading(''); } catch (error) { console.error('Error sending message:', error); @@ -186,10 +175,8 @@ const isOpenCamera = searchParams.get('camera') === 'open'; function formatBoldText(text) { const parts = text.split(/(\*\*[^\*]+\*\*)/g); - return parts.flatMap((part, index) => { const elements = []; - if (part.startsWith('**') && part.endsWith('**')) { part = part.slice(2, -2); part.split('\n').forEach((line, i) => { @@ -202,7 +189,6 @@ const isOpenCamera = searchParams.get('camera') === 'open'; elements.push({line}); }); } - return elements; }); } @@ -215,7 +201,7 @@ const isOpenCamera = searchParams.get('camera') === 'open';
- {isLoading != '' && ( + {isLoading !== '' && (
{isLoading} @@ -223,39 +209,30 @@ const isOpenCamera = searchParams.get('camera') === 'open';
)} {messages.slice().reverse().map((msg, index) => ( -
+
- {msg.sender !== 'bot' - ? (msg.text ? - msg.text - : - - ) - : (() => { + {msg.sender !== 'bot' ? ( + msg.text ? msg.text : + ) : ( + (() => { try { return formatBoldText(msg.text); } catch (e) { return msg.text; } - })()} + })() + )} {msg.quickReplies && (
{msg.quickReplies.map((reply, i) => ( -
sendMessage(reply)} - > +
sendMessage(reply)}> {reply}
))}
setSearchParams({ camera: 'open' })} - style={{ color: 'white', backgroundColor: '#075e54', display: 'flex', flexDirection: 'row', alignItems: 'center' }} + style={{ color: 'white', backgroundColor: '#075e54', display: 'flex', alignItems: 'center' }} > Analisa Gambar @@ -275,27 +252,17 @@ const isOpenCamera = searchParams.get('camera') === 'open'; value={input} onChange={(e) => setInput(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && sendMessage()} - disabled={isLoading != ''} + disabled={isLoading !== ''} /> - - - -
- {isPoppedUp !== '' && + {isPoppedUp !== '' && (
Untuk bisa membantu Anda lebih jauh, boleh saya tahu nama dan nomor telepon Anda? @@ -326,7 +293,6 @@ const isOpenCamera = searchParams.get('camera') === 'open'; }} />
-
{ @@ -336,7 +302,11 @@ const isOpenCamera = searchParams.get('camera') === 'open'; sessionData.phoneNumber = phoneNumber; sessionStorage.setItem('session', JSON.stringify(sessionData)); setIsPoppedUp(''); - sendMessage(isPoppedUp); + if (typeof isPoppedUp === 'string' && isPoppedUp.startsWith('data:image/')) { + handleUploadImage(isPoppedUp); + } else { + sendMessage(isPoppedUp); + } } }} > @@ -345,7 +315,7 @@ const isOpenCamera = searchParams.get('camera') === 'open';
- } + )} {isOpenCamera && ( { const [weeklyData, setWeeklyData] = useState([]); const [allTimeData, setAllTimeData] = useState([]); + const [faceAnalystList, setFaceAnalystList] = useState([]); const [conversations, setConversations] = useState([]); const [followUps, setFollowUps] = useState([]); @@ -318,6 +319,8 @@ function parseGraphData(graph) { try{ console.log(data); setDiscussedTopics(data[0]?.graph[0]?.json?.result?.topics) + setFaceAnalystList(data[0]?.graph[0]?.json?.result?.analyst_counter); + setFollowUps(data[0]?.graph[0]?.json?.result?.interested_users) setFileList(data[0]?.files) setUpdateDetected(data[1]?.updateDetected) @@ -437,7 +440,7 @@ function parseGraphData(graph) { }; const openTopicsModal = () => { - setModalContent(); + setModalContent(); }; const handleDeleteFile = async (key) => { diff --git a/src/DiscussedTopics.js b/src/DiscussedTopics.js index 7735ced..f53943d 100644 --- a/src/DiscussedTopics.js +++ b/src/DiscussedTopics.js @@ -1,32 +1,66 @@ // DiscussedTopics.js -import React from 'react'; +import React, { useState } from 'react'; import styles from './DiscussedTopics.module.css'; -const DiscussedTopics = ({ topics }) => { +const DiscussedTopics = ({ topics, faceAnalystList }) => { + const [activeTab, setActiveTab] = useState('topics'); // 'topics' or 'face' + return (
-

Top Topic

+
+ + +
- {topics.length} topik + {activeTab === 'topics' + ? `${topics.length} topik` + : `${faceAnalystList.length} report`}
- {topics.length === 0 ? ( + {activeTab === 'topics' ? ( + topics.length === 0 ? ( +
+
💬
+

Discussed Topic Is Empty

+
+ ) : ( + topics.map((topic, idx) => ( +
+
+

{topic.topic}

+
+ {topic.count} + times +
+
+
+ )) + ) + ) : faceAnalystList.length === 0 ? (
-
💬
-

Discussed Topic Is Empty

+
🧑‍⚕️
+

No Face Analyst Report

) : ( - topics.map((topic, idx) => ( + faceAnalystList.map((item, idx) => (
-

{topic.topic}

-
- {topic.count} - times -
+

{item.name}

+

{item.description}

+

📞 {item.phone_number}

)) @@ -36,4 +70,4 @@ const DiscussedTopics = ({ topics }) => { ); }; -export default DiscussedTopics; \ No newline at end of file +export default DiscussedTopics; diff --git a/src/DiscussedTopics.module.css b/src/DiscussedTopics.module.css index 86ae0e5..b0087c8 100644 --- a/src/DiscussedTopics.module.css +++ b/src/DiscussedTopics.module.css @@ -184,4 +184,35 @@ .countLabel { font-size: 11px; } -} \ No newline at end of file +} + +.tabButtons { + display: flex; + gap: 10px; +} + +.tabButton { + background-color: #eee; + border: none; + padding: 6px 12px; + border-radius: 8px; + cursor: pointer; + font-weight: 500; +} + +.activeTab { + background-color: #007bff; + color: white; +} + +.description { + margin-top: 6px; + font-size: 0.95rem; + color: #444; +} + +.phone { + margin-top: 4px; + font-size: 0.85rem; + color: #666; +}