294 lines
14 KiB
React
294 lines
14 KiB
React
import React, { useState } from 'react';
|
||
import { useApp } from '../context/AppContext';
|
||
import { Globe, Bot, Sparkles, CheckCircle2, ShieldCheck, Tag, X, Loader2, Database, ArrowRight } from 'lucide-react';
|
||
import confetti from 'canvas-confetti';
|
||
|
||
export const CompanyScannerModal = () => {
|
||
const { isCompanyScannerOpen, setIsCompanyScannerOpen, userProfile, scanCompanyWebsite, updateCompanyCapabilities } = useApp();
|
||
|
||
const [urlInput, setUrlInput] = useState(userProfile.website || 'https://www.tanriverdimedikal.com.tr');
|
||
const [isScanning, setIsScanning] = useState(false);
|
||
const [scanStep, setScanStep] = useState(0);
|
||
const [scanSuccess, setScanSuccess] = useState(false);
|
||
|
||
const [newProductInput, setNewProductInput] = useState('');
|
||
|
||
if (!isCompanyScannerOpen) return null;
|
||
|
||
const handleStartScan = async (e) => {
|
||
e.preventDefault();
|
||
if (!urlInput.trim()) return;
|
||
|
||
setIsScanning(true);
|
||
setScanSuccess(false);
|
||
setScanStep(1);
|
||
|
||
setTimeout(() => setScanStep(2), 600);
|
||
setTimeout(() => setScanStep(3), 1200);
|
||
|
||
const capabilities = await scanCompanyWebsite(urlInput);
|
||
setIsScanning(false);
|
||
setScanSuccess(true);
|
||
confetti({ particleCount: 70, spread: 60 });
|
||
};
|
||
|
||
const caps = userProfile.scrapedCapabilities;
|
||
|
||
const handleRemoveSector = (indexToRemove) => {
|
||
if (!caps?.extractedSectors) return;
|
||
const updated = caps.extractedSectors.filter((_, idx) => idx !== indexToRemove);
|
||
updateCompanyCapabilities({ extractedSectors: updated });
|
||
};
|
||
|
||
const handleRemoveProduct = (indexToRemove) => {
|
||
if (!caps?.extractedProducts) return;
|
||
const updated = caps.extractedProducts.filter((_, idx) => idx !== indexToRemove);
|
||
updateCompanyCapabilities({ extractedProducts: updated });
|
||
};
|
||
|
||
const handleRemoveCert = (indexToRemove) => {
|
||
if (!caps?.extractedCertifications) return;
|
||
const updated = caps.extractedCertifications.filter((_, idx) => idx !== indexToRemove);
|
||
updateCompanyCapabilities({ extractedCertifications: updated });
|
||
};
|
||
|
||
const handleAddCustomProduct = (e) => {
|
||
e.preventDefault();
|
||
if (!newProductInput.trim() || !caps) return;
|
||
const updated = [...(caps.extractedProducts || []), newProductInput.trim()];
|
||
updateCompanyCapabilities({ extractedProducts: updated });
|
||
setNewProductInput('');
|
||
};
|
||
|
||
return (
|
||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-slate-900/70 backdrop-blur-xs animate-fade-in">
|
||
<div className="bg-white rounded-2xl border border-slate-200 shadow-2xl w-full max-w-3xl overflow-hidden my-auto flex flex-col max-h-[92vh]">
|
||
|
||
{/* Header */}
|
||
<div className="bg-linear-to-r from-blue-900 via-slate-900 to-indigo-900 text-white px-6 py-4 flex items-center justify-between">
|
||
<div className="flex items-center gap-3">
|
||
<div className="w-10 h-10 rounded-xl bg-blue-600 flex items-center justify-center text-white shadow-md">
|
||
<Globe className="w-6 h-6" />
|
||
</div>
|
||
<div>
|
||
<h2 className="font-extrabold text-base flex items-center gap-2">
|
||
Firma Web Sitesi Tarama & Detaylı Ürün Analiz Motoru
|
||
</h2>
|
||
<p className="text-xs text-blue-200">Sayfalarınızdaki gerçek ürün ve faaliyet kollarını tarar, alakasız harici sektörleri kesinlikle engeller.</p>
|
||
</div>
|
||
</div>
|
||
<button
|
||
onClick={() => setIsCompanyScannerOpen(false)}
|
||
className="text-slate-400 hover:text-white p-1 rounded-lg transition-colors"
|
||
>
|
||
<X className="w-6 h-6" />
|
||
</button>
|
||
</div>
|
||
|
||
{/* Modal Body */}
|
||
<div className="p-6 space-y-6 overflow-y-auto">
|
||
|
||
{/* Strict Sector Protection Banner */}
|
||
<div className="bg-blue-50 border border-blue-200 rounded-xl p-3 flex items-center justify-between text-xs text-blue-900">
|
||
<div className="flex items-center gap-2 font-bold">
|
||
<ShieldCheck className="w-4 h-4 text-blue-600" />
|
||
<span>Sektör Filtresi Aktif: Sadece web sitenizdeki kesinleşmiş faaliyet alanları ve detaylı ürün kataloğu işlenir.</span>
|
||
</div>
|
||
<span className="bg-blue-600 text-white text-[10px] font-extrabold px-2 py-0.5 rounded-full">
|
||
Sıfır Alakasız Sektör Garantisi
|
||
</span>
|
||
</div>
|
||
|
||
{/* URL Form */}
|
||
<form onSubmit={handleStartScan} className="bg-slate-50 p-4 rounded-xl border border-slate-200 space-y-3">
|
||
<label className="block text-xs font-bold text-slate-800 uppercase tracking-wider">
|
||
FİRMANIZA AİT WEB SİTESİ ADRESİ
|
||
</label>
|
||
<div className="flex gap-2">
|
||
<div className="relative flex-1">
|
||
<Globe className="w-4 h-4 text-slate-400 absolute left-3 top-1/2 -translate-y-1/2" />
|
||
<input
|
||
type="url"
|
||
required
|
||
value={urlInput}
|
||
onChange={(e) => setUrlInput(e.target.value)}
|
||
placeholder="https://www.firmaniz.com.tr"
|
||
className="w-full bg-white border border-slate-300 rounded-lg pl-9 pr-4 py-2.5 text-xs text-slate-900 font-semibold focus:ring-2 focus:ring-blue-500"
|
||
/>
|
||
</div>
|
||
<button
|
||
type="submit"
|
||
disabled={isScanning}
|
||
className="bg-blue-600 hover:bg-blue-500 text-white font-extrabold px-5 py-2.5 rounded-lg text-xs flex items-center gap-2 transition-colors shadow-md disabled:opacity-50 shrink-0"
|
||
>
|
||
{isScanning ? <Loader2 className="w-4 h-4 animate-spin" /> : <Sparkles className="w-4 h-4 text-amber-300" />}
|
||
<span>{isScanning ? 'Detaylı Ürünler Taranıyor...' : 'Web Sitemi Tara & Profili Güncelle'}</span>
|
||
</button>
|
||
</div>
|
||
</form>
|
||
|
||
{/* Scanning Live Indicator */}
|
||
{isScanning && (
|
||
<div className="bg-blue-50 border border-blue-200 p-5 rounded-xl space-y-3 animate-fade-in">
|
||
<div className="flex items-center justify-between text-xs font-extrabold text-blue-900">
|
||
<span className="flex items-center gap-2">
|
||
<Loader2 className="w-4 h-4 text-blue-600 animate-spin" />
|
||
Derin Sayfa Metin Analizi ve Ürün Çıkarımı Sürüyor...
|
||
</span>
|
||
<span>%{(scanStep * 33).toFixed(0)}</span>
|
||
</div>
|
||
|
||
<div className="w-full bg-blue-200 rounded-full h-2 overflow-hidden">
|
||
<div
|
||
className="bg-blue-600 h-2 rounded-full transition-all duration-500"
|
||
style={{ width: `${scanStep * 33}%` }}
|
||
/>
|
||
</div>
|
||
|
||
<div className="space-y-1 text-xs text-slate-600 font-medium">
|
||
<p className={scanStep >= 1 ? 'text-blue-900 font-bold' : 'text-slate-400'}>
|
||
1. 🌐 {urlInput} alan adına bağlanıldı, harici ve alakasız sektör tanımları elendi.
|
||
</p>
|
||
<p className={scanStep >= 2 ? 'text-blue-900 font-bold' : 'text-slate-400'}>
|
||
2. 📄 Web sitesindeki "Hakkımızda", "Ürünler" ve "Katalog" alt sayfalarındaki ürün isimleri ayıklandı.
|
||
</p>
|
||
<p className={scanStep >= 3 ? 'text-blue-900 font-bold' : 'text-slate-400'}>
|
||
3. 💾 Firmanın gerçek ürün yelpazesi ve ISO/ÜTS kalite belgeleri İhaleist veritabanına işlendi.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{scanSuccess && (
|
||
<div className="bg-emerald-50 border border-emerald-200 text-emerald-900 p-4 rounded-xl text-xs font-bold flex items-center gap-2 animate-fade-in shadow-xs">
|
||
<CheckCircle2 className="w-5 h-5 text-emerald-600 shrink-0" />
|
||
<span>Web sitenizdeki ürünler ve doğrudan doğrulanmış sektörler veritabanına işlendi! Alakasız sektörler elendi.</span>
|
||
</div>
|
||
)}
|
||
|
||
{/* Current Extracted Capabilities Database View */}
|
||
{caps && (
|
||
<div className="space-y-4">
|
||
<div className="flex items-center justify-between border-b border-slate-200 pb-2">
|
||
<h3 className="font-extrabold text-sm text-slate-900 flex items-center gap-2">
|
||
<Database className="w-4 h-4 text-blue-600" /> Veritabanındaki Doğrulanmış Firma Ürün & Sektör Profili
|
||
</h3>
|
||
<span className="text-[10px] text-slate-400 font-semibold">Son Tarama: {caps.scrapedAt}</span>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||
|
||
{/* Sectors */}
|
||
<div className="bg-slate-50 p-4 rounded-xl border border-slate-200 space-y-2">
|
||
<span className="font-bold text-xs text-slate-800 uppercase tracking-wider flex items-center gap-1.5">
|
||
<Tag className="w-3.5 h-3.5 text-blue-600" /> Doğrulanmış Sektörler ({caps.extractedSectors?.length || 0})
|
||
</span>
|
||
<div className="space-y-1.5">
|
||
{caps.extractedSectors?.map((s, i) => (
|
||
<div key={i} className="flex items-center justify-between text-xs font-bold text-blue-900 bg-blue-100/70 border border-blue-200 px-2.5 py-1.5 rounded-lg group">
|
||
<span>{s}</span>
|
||
<button
|
||
type="button"
|
||
onClick={() => handleRemoveSector(i)}
|
||
className="text-blue-400 hover:text-red-600 transition-colors p-0.5"
|
||
title="Sektörü Kaldır"
|
||
>
|
||
<X className="w-3.5 h-3.5" />
|
||
</button>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* Products */}
|
||
<div className="bg-slate-50 p-4 rounded-xl border border-slate-200 space-y-3 md:col-span-2">
|
||
<span className="font-bold text-xs text-slate-800 uppercase tracking-wider flex items-center gap-1.5 justify-between">
|
||
<span className="flex items-center gap-1.5">
|
||
<Bot className="w-3.5 h-3.5 text-emerald-600" /> Detaylı Ürün & Hizmet Kataloğu ({caps.extractedProducts?.length || 0})
|
||
</span>
|
||
<span className="text-[10px] text-emerald-700 font-semibold">Sayfadan Ayıklanan Detaylı Kalemler</span>
|
||
</span>
|
||
|
||
{/* Add Custom Item Form */}
|
||
<form onSubmit={handleAddCustomProduct} className="flex gap-2">
|
||
<input
|
||
type="text"
|
||
value={newProductInput}
|
||
onChange={(e) => setNewProductInput(e.target.value)}
|
||
placeholder="+ Yeni Ürün / İhale Kalemi Ekle..."
|
||
className="flex-1 bg-white border border-slate-300 rounded-lg px-3 py-1.5 text-xs text-slate-900 font-semibold focus:ring-2 focus:ring-emerald-500"
|
||
/>
|
||
<button
|
||
type="submit"
|
||
className="bg-emerald-600 hover:bg-emerald-500 text-white font-bold px-3 py-1.5 rounded-lg text-xs transition-colors shrink-0"
|
||
>
|
||
Ekle
|
||
</button>
|
||
</form>
|
||
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-1.5">
|
||
{caps.extractedProducts?.map((p, i) => (
|
||
<div key={i} className="text-xs font-semibold text-slate-700 bg-white border border-slate-200 p-2 rounded-lg flex items-start justify-between gap-1.5 group">
|
||
<div className="flex items-start gap-1.5">
|
||
<span className="shrink-0 text-emerald-600 font-bold">📦</span>
|
||
<span className="line-clamp-2">{p}</span>
|
||
</div>
|
||
<button
|
||
type="button"
|
||
onClick={() => handleRemoveProduct(i)}
|
||
className="text-slate-300 hover:text-red-600 transition-colors p-0.5 shrink-0"
|
||
title="Ürünü Kaldır"
|
||
>
|
||
<X className="w-3.5 h-3.5" />
|
||
</button>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
{/* Certifications */}
|
||
<div className="bg-slate-50 p-4 rounded-xl border border-slate-200 space-y-2">
|
||
<span className="font-bold text-xs text-slate-800 uppercase tracking-wider flex items-center gap-1.5">
|
||
<ShieldCheck className="w-3.5 h-3.5 text-purple-600" /> Web Sitesinde Tespit Edilen Sertifika ve Kayıtlar
|
||
</span>
|
||
<div className="flex flex-wrap gap-2">
|
||
{caps.extractedCertifications?.map((c, i) => (
|
||
<span key={i} className="text-xs font-semibold text-purple-900 bg-purple-100/70 border border-purple-200 px-3 py-1 rounded-lg flex items-center gap-1.5">
|
||
📜 {c}
|
||
<button
|
||
type="button"
|
||
onClick={() => handleRemoveCert(i)}
|
||
className="text-purple-400 hover:text-red-600 transition-colors"
|
||
>
|
||
<X className="w-3 h-3" />
|
||
</button>
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
)}
|
||
|
||
</div>
|
||
|
||
{/* Footer */}
|
||
<div className="bg-slate-50 p-4 border-t border-slate-200 flex justify-between items-center">
|
||
<p className="text-[11px] text-slate-500 font-medium">
|
||
💡 Sayfalarınızdaki detaylı ürün kataloğu sayesinde AI ihale eşleşme doğruluk skorunuz <strong className="text-emerald-600">%98+</strong> seviyesine çıkarılır.
|
||
</p>
|
||
<button
|
||
onClick={() => setIsCompanyScannerOpen(false)}
|
||
className="bg-slate-800 hover:bg-slate-700 text-white font-bold text-xs px-6 py-2.5 rounded-lg transition-colors shadow-xs shrink-0"
|
||
>
|
||
Tamam & Profili Kaydet
|
||
</button>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|