Spaces:
Running
Running
| <html lang="id"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>ChiliCare AI</title> | |
| <link | |
| href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" | |
| rel="stylesheet" | |
| /> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script> | |
| tailwind.config = { | |
| theme: { | |
| extend: { | |
| fontFamily: { sans: ["Inter", "sans-serif"] }, | |
| }, | |
| }, | |
| }; | |
| </script> | |
| <style> | |
| .dot-flashing { | |
| position: relative; | |
| width: 6px; | |
| height: 6px; | |
| border-radius: 5px; | |
| background-color: #f43f5e; | |
| color: #f43f5e; | |
| animation: dot-flashing 1s infinite linear alternate; | |
| animation-delay: 0.5s; | |
| } | |
| .dot-flashing::before, | |
| .dot-flashing::after { | |
| content: ""; | |
| display: inline-block; | |
| position: absolute; | |
| top: 0; | |
| width: 6px; | |
| height: 6px; | |
| border-radius: 5px; | |
| background-color: #f43f5e; | |
| color: #f43f5e; | |
| animation: dot-flashing 1s infinite alternate; | |
| } | |
| .dot-flashing::before { | |
| left: -10px; | |
| animation-delay: 0s; | |
| } | |
| .dot-flashing::after { | |
| left: 10px; | |
| animation-delay: 1s; | |
| } | |
| @keyframes dot-flashing { | |
| 0% { | |
| background-color: #f43f5e; | |
| } | |
| 50%, | |
| 100% { | |
| background-color: rgba(244, 63, 94, 0.2); | |
| } | |
| } | |
| ::-webkit-scrollbar { | |
| width: 6px; | |
| height: 6px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #cbd5e1; | |
| border-radius: 10px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: #94a3b8; | |
| } | |
| .hide-scrollbar::-webkit-scrollbar { | |
| display: none; | |
| } | |
| .hide-scrollbar { | |
| -ms-overflow-style: none; | |
| scrollbar-width: none; | |
| } | |
| </style> | |
| </head> | |
| <body | |
| class="flex flex-col md:flex-row h-[100dvh] bg-slate-50 text-slate-800 font-sans antialiased selection:bg-rose-200 overflow-hidden" | |
| > | |
| <aside | |
| class="w-full md:w-80 bg-white border-b md:border-b-0 md:border-r border-slate-100 flex flex-col justify-between shrink-0 shadow-sm md:shadow-[4px_0_24px_rgba(0,0,0,0.02)] z-20 relative" | |
| > | |
| <div class="p-4 md:p-6"> | |
| <div class="flex items-center gap-3 mb-4 md:mb-8"> | |
| <div | |
| class="w-8 h-8 md:w-10 md:h-10 rounded-xl bg-gradient-to-br from-rose-500 to-orange-400 flex items-center justify-center text-white text-base md:text-xl shadow-lg shadow-rose-200/50 shrink-0" | |
| > | |
| 🌶️ | |
| </div> | |
| <h1 | |
| class="text-lg md:text-xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-slate-800 to-slate-600 tracking-tight" | |
| > | |
| ChiliCare AI | |
| </h1> | |
| </div> | |
| <p | |
| class="hidden md:block text-xs font-semibold text-slate-400 uppercase tracking-wider mb-3 px-2" | |
| > | |
| Menu Utama | |
| </p> | |
| <div | |
| class="flex flex-row md:flex-col gap-2 overflow-x-auto hide-scrollbar w-full pb-1 md:pb-0" | |
| > | |
| <button | |
| id="btn-menu-detect" | |
| onclick="switchMenu('detect')" | |
| class="flex-1 md:w-full flex items-center justify-center md:justify-start gap-2 md:gap-3 px-4 py-2.5 md:py-3 rounded-xl font-medium transition-all bg-rose-50 text-rose-600 text-sm md:text-base whitespace-nowrap" | |
| > | |
| <svg | |
| class="w-5 h-5 shrink-0" | |
| fill="none" | |
| stroke="currentColor" | |
| viewBox="0 0 24 24" | |
| > | |
| <path | |
| stroke-linecap="round" | |
| stroke-linejoin="round" | |
| stroke-width="2" | |
| d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z" | |
| ></path> | |
| <path | |
| stroke-linecap="round" | |
| stroke-linejoin="round" | |
| stroke-width="2" | |
| d="M15 13a3 3 0 11-6 0 3 3 0 016 0z" | |
| ></path> | |
| </svg> | |
| Deteksi Penyakit | |
| </button> | |
| <button | |
| id="btn-menu-chat" | |
| onclick="switchMenu('chat')" | |
| class="flex-1 md:w-full flex items-center justify-center md:justify-start gap-2 md:gap-3 px-4 py-2.5 md:py-3 rounded-xl font-medium transition-all text-slate-500 hover:bg-slate-50 hover:text-slate-700 text-sm md:text-base whitespace-nowrap" | |
| > | |
| <svg | |
| class="w-5 h-5 shrink-0" | |
| fill="none" | |
| stroke="currentColor" | |
| viewBox="0 0 24 24" | |
| > | |
| <path | |
| stroke-linecap="round" | |
| stroke-linejoin="round" | |
| stroke-width="2" | |
| d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" | |
| ></path> | |
| </svg> | |
| Chatbot Ahli | |
| </button> | |
| </div> | |
| </div> | |
| <div | |
| class="hidden md:block p-6 bg-slate-50/50 m-4 rounded-2xl ring-1 ring-slate-100" | |
| > | |
| <h3 class="font-semibold text-sm mb-3 text-slate-700"> | |
| Spesifikasi Model AI | |
| </h3> | |
| <div class="text-xs text-slate-500 space-y-3"> | |
| <div> | |
| <strong class="text-slate-600 block mb-1">1. Vision</strong | |
| ><span | |
| class="bg-white ring-1 ring-slate-200 px-2 py-0.5 rounded-md shadow-sm" | |
| >YOLOv11s</span | |
| > | |
| </div> | |
| <div> | |
| <strong class="text-slate-600 block mb-1">2. RAG</strong | |
| ><span | |
| class="bg-white ring-1 ring-slate-200 px-2 py-0.5 rounded-md shadow-sm" | |
| >ChromaDB</span | |
| > | |
| </div> | |
| <div> | |
| <strong class="text-slate-600 block mb-1">3. LLM</strong | |
| ><span | |
| class="bg-white ring-1 ring-slate-200 px-2 py-0.5 rounded-md shadow-sm" | |
| >Nemotron-3</span | |
| > | |
| </div> | |
| </div> | |
| </div> | |
| </aside> | |
| <main | |
| class="flex-1 overflow-y-auto bg-[#FAFAFA] relative scroll-smooth h-full" | |
| > | |
| <div | |
| id="section-detect" | |
| class="block max-w-4xl mx-auto p-4 md:p-10 pb-24 md:pb-24" | |
| > | |
| <header class="mb-6 md:mb-10 text-center mt-4 md:mt-0"> | |
| <h2 | |
| class="text-2xl md:text-3xl font-bold tracking-tight text-slate-800 mb-2 md:mb-3" | |
| > | |
| Analisis Daun Cabai | |
| </h2> | |
| <p class="text-sm md:text-base text-slate-500 px-4"> | |
| Unggah foto daun cabai yang bermasalah untuk diagnosis instan | |
| berbasis YOLO. | |
| </p> | |
| </header> | |
| <div | |
| class="bg-white p-2 rounded-3xl shadow-sm ring-1 ring-slate-200 mb-6 md:mb-8 max-w-2xl mx-auto" | |
| > | |
| <label for="file-upload" class="relative flex flex-col items-center justify-center w-full h-64 border-2 border-dashed border-slate-300 rounded-2xl cursor-pointer hover:bg-slate-50 transition-colors overflow-hidden group"> | |
| <div id="upload-placeholder" class="flex flex-col items-center justify-center transition-opacity duration-300"> | |
| <div class="p-3 bg-white shadow-sm ring-1 ring-slate-100 rounded-full mb-3 group-hover:scale-110 transition-transform"> | |
| <svg class="w-6 h-6 text-rose-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"></path></svg> | |
| </div> | |
| <p class="text-sm text-slate-600 font-medium">Pilih gambar daun</p> | |
| </div> | |
| <img id="image-preview" class="hidden absolute inset-0 w-full h-full object-cover z-10" alt="Preview Daun" /> | |
| </label> | |
| <input id="file-upload" type="file" accept="image/*" class="hidden" onchange="handleFileChange(event)" /> | |
| <input | |
| type="file" | |
| accept="image/jpeg, image/png, image/jpg" | |
| id="file-upload" | |
| class="hidden" | |
| onchange="handleFileChange(event)" | |
| /> | |
| </div> | |
| <p | |
| id="file-name" | |
| class="text-center text-sm font-medium text-slate-500 mb-6 hidden" | |
| ></p> | |
| <div id="preview-container" class="mb-8 flex justify-center hidden"> | |
| <img | |
| id="image-preview" | |
| class="max-h-56 md:max-h-72 rounded-2xl shadow-lg ring-1 ring-slate-900/5 object-cover" | |
| alt="Preview" | |
| /> | |
| </div> | |
| <div class="flex justify-center"> | |
| <button | |
| id="btn-upload" | |
| onclick="handleUpload()" | |
| class="hidden w-full max-w-sm bg-gradient-to-r from-rose-500 to-rose-600 text-white font-semibold py-3.5 px-6 rounded-full shadow-lg shadow-rose-500/30 hover:shadow-rose-500/50 transition-all disabled:opacity-70" | |
| > | |
| Mulai Analisis AI | |
| </button> | |
| </div> | |
| <div | |
| id="detect-error" | |
| class="hidden mt-8 p-4 bg-red-50 text-red-600 ring-1 ring-red-100 rounded-2xl text-sm font-medium text-center max-w-2xl mx-auto" | |
| ></div> | |
| <div id="detect-result" class="hidden mt-10 md:mt-14 max-w-2xl mx-auto"> | |
| <h3 | |
| class="text-lg md:text-xl font-bold text-slate-800 mb-4 md:mb-6 flex items-center gap-2" | |
| > | |
| Hasil Diagnosis (YOLOv11 & LLM) | |
| </h3> | |
| <div | |
| class="bg-white p-2 md:p-4 rounded-3xl shadow-sm ring-1 ring-slate-200 mb-6" | |
| > | |
| <img | |
| id="result-image" | |
| class="w-full rounded-2xl object-cover" | |
| alt="Hasil Deteksi" | |
| /> | |
| </div> | |
| <div id="result-details" class="space-y-4"></div> | |
| </div> | |
| </div> | |
| <div | |
| id="section-chat" | |
| class="hidden flex-col h-full max-w-4xl mx-auto relative" | |
| > | |
| <header | |
| class="p-4 md:p-8 pb-4 sticky top-0 bg-[#FAFAFA]/90 backdrop-blur-xl z-10 border-b border-slate-200/50" | |
| > | |
| <h2 | |
| class="text-xl md:text-2xl font-bold text-slate-800 flex items-center gap-2" | |
| > | |
| Asisten Ahli Cabai | |
| </h2> | |
| <p class="text-xs md:text-sm text-slate-500 mt-1"> | |
| Tanyakan seputar perawatan, penyakit, atau pupuk. | |
| </p> | |
| </header> | |
| <div | |
| id="chat-messages" | |
| class="flex-1 overflow-y-auto p-4 md:p-8 space-y-4 md:space-y-6 pb-28 md:pb-32" | |
| > | |
| <div | |
| id="chat-empty" | |
| class="h-full flex flex-col items-center justify-center text-slate-400 space-y-4 mt-4 md:mt-10" | |
| > | |
| <div | |
| class="w-12 h-12 md:w-16 md:h-16 rounded-full bg-slate-100 flex items-center justify-center text-xl md:text-2xl" | |
| > | |
| 💬 | |
| </div> | |
| <p class="text-sm md:text-base text-center"> | |
| Kirim pesan untuk memulai percakapan... | |
| </p> | |
| </div> | |
| </div> | |
| <div class="absolute bottom-4 md:bottom-6 left-0 w-full px-4 md:px-8"> | |
| <form | |
| id="chat-form" | |
| onsubmit="handleSendChat(event)" | |
| class="bg-white p-1.5 md:p-2 rounded-full shadow-[0_8px_30px_rgb(0,0,0,0.08)] ring-1 ring-slate-200 flex gap-2 items-center" | |
| > | |
| <input | |
| type="text" | |
| id="chat-input" | |
| placeholder="Tanyakan sesuatu..." | |
| class="flex-1 bg-transparent border-none px-4 md:px-6 py-2.5 md:py-3 text-sm md:text-base text-slate-700 focus:outline-none focus:ring-0 placeholder-slate-400" | |
| autocomplete="off" | |
| required | |
| /> | |
| <button | |
| type="submit" | |
| id="btn-chat-send" | |
| class="bg-rose-500 text-white p-2.5 md:p-3 rounded-full hover:bg-rose-600 disabled:opacity-50 flex items-center justify-center w-10 h-10 md:w-12 md:h-12 shrink-0" | |
| > | |
| <svg | |
| class="w-4 h-4 md:w-5 md:h-5" | |
| fill="none" | |
| stroke="currentColor" | |
| viewBox="0 0 24 24" | |
| > | |
| <path | |
| stroke-linecap="round" | |
| stroke-linejoin="round" | |
| stroke-width="2.5" | |
| d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" | |
| ></path> | |
| </svg> | |
| </button> | |
| </form> | |
| </div> | |
| </div> | |
| </main> | |
| <script src="script.js"></script> | |
| </body> | |
| </html> | |