fh / src /components /UploadSection_NEW.svelte
Varun10000's picture
Upload 57 files
d8635c9 verified
Raw
History Blame Contribute Delete
14.4 kB
<script lang="ts">
import { previousRfps, nextStep } from '../stores/appStore'
import { parseDocument } from '../utils/documentParser'
let dragActive = false
let isProcessing = false
let uploadedFiles: File[] = []
let processingStatus = ''
let analysisResults: any[] = []
// For accuracy, we'll scan the local folder as well
let folderPath = 'c:\\Users\\varun\\Downloads\\RFP Svelt\\public\\previous-rfps'
async function handleFileUpload(event: Event) {
const target = event.target as HTMLInputElement
if (target.files) {
await processFiles(Array.from(target.files))
}
}
async function processFiles(files: File[]) {
isProcessing = true
processingStatus = 'Analyzing documents for accuracy...'
uploadedFiles = [...uploadedFiles, ...files]
try {
for (const file of files) {
processingStatus = `Processing ${file.name}...`
const content = await parseDocument(file)
// Enhanced analysis for accuracy
const analysis = analyzeDocumentQuality(content, file.name)
analysisResults.push(analysis)
const rfpDocument = {
id: `rfp-${Date.now()}-${Math.random()}`,
name: file.name,
content: content,
size: file.size,
uploadDate: new Date().toISOString(),
pageCount: Math.ceil(content.length / 2000), // Estimate pages
quality: analysis.quality,
keyTopics: analysis.topics,
wordCount: content.split(' ').length
}
previousRfps.update(current => [...current, rfpDocument])
}
processingStatus = 'Analysis complete! Documents ready for AI reference.'
} catch (error) {
console.error('Error processing files:', error)
processingStatus = 'Error processing some files. Please check format and try again.'
} finally {
setTimeout(() => {
isProcessing = false
processingStatus = ''
}, 2000)
}
}
function analyzeDocumentQuality(content: string, filename: string) {
const wordCount = content.split(' ').length
const hasQuestions = /\?|what|how|when|where|why|describe|explain|provide/gi.test(content)
const hasAnswers = content.length > 5000 // Substantial content
const hasStructure = /section|chapter|\d+\.|bullet|β€’/gi.test(content)
let quality = 'Basic'
let score = 0
if (wordCount > 1000) score += 25
if (wordCount > 5000) score += 25
if (hasQuestions) score += 20
if (hasAnswers) score += 20
if (hasStructure) score += 10
if (score >= 80) quality = 'Excellent'
else if (score >= 60) quality = 'Good'
else if (score >= 40) quality = 'Fair'
// Extract key topics
const topics = extractKeyTopics(content)
return {
quality,
score,
topics,
wordCount,
hasQuestions,
hasAnswers,
hasStructure,
recommendations: getRecommendations(score, hasQuestions, hasAnswers)
}
}
function extractKeyTopics(content: string) {
const businessTerms = [
'security', 'compliance', 'implementation', 'timeline', 'budget', 'experience',
'methodology', 'team', 'project management', 'deliverables', 'support',
'training', 'maintenance', 'scalability', 'performance', 'integration'
]
return businessTerms.filter(term =>
content.toLowerCase().includes(term)
).slice(0, 5)
}
function getRecommendations(score: number, hasQuestions: boolean, hasAnswers: boolean) {
const recommendations = []
if (score < 40) {
recommendations.push('Consider adding more detailed RFP responses')
}
if (!hasQuestions) {
recommendations.push('Include documents with both questions and answers')
}
if (!hasAnswers) {
recommendations.push('Add more comprehensive response content')
}
if (score >= 80) {
recommendations.push('Excellent reference material for AI training')
}
return recommendations
}
function handleDrop(event: DragEvent) {
event.preventDefault()
dragActive = false
if (event.dataTransfer?.files) {
processFiles(Array.from(event.dataTransfer.files))
}
}
function handleDragOver(event: DragEvent) {
event.preventDefault()
dragActive = true
}
function handleDragLeave() {
dragActive = false
}
function removeDocument(id: string) {
previousRfps.update(current => current.filter(doc => doc.id !== id))
uploadedFiles = uploadedFiles.filter((_, index) => $previousRfps[index]?.id !== id)
}
function proceedToNextStep() {
if ($previousRfps.length > 0) {
nextStep()
}
}
function getQualityColor(quality: string) {
switch (quality) {
case 'Excellent': return 'text-green-600 bg-green-100 border-green-200'
case 'Good': return 'text-blue-600 bg-blue-100 border-blue-200'
case 'Fair': return 'text-yellow-600 bg-yellow-100 border-yellow-200'
default: return 'text-gray-600 bg-gray-100 border-gray-200'
}
}
</script>
<div class="space-y-8">
<!-- Instructions Section -->
<div class="bg-gradient-to-r from-blue-50 to-indigo-50 rounded-2xl p-6 border border-blue-200">
<div class="flex items-start space-x-4">
<div class="w-12 h-12 bg-blue-500 rounded-xl flex items-center justify-center text-white text-2xl">
πŸ’‘
</div>
<div class="flex-1">
<h3 class="text-lg font-bold text-blue-900 mb-2">For Maximum Accuracy</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm text-blue-800">
<div>
<h4 class="font-semibold mb-1">πŸ“ Folder Method (Recommended)</h4>
<p>Add PDFs to: <code class="bg-blue-200 px-2 py-1 rounded text-xs">public/previous-rfps/</code></p>
</div>
<div>
<h4 class="font-semibold mb-1">πŸ“€ Upload Method</h4>
<p>Drag & drop your best RFP responses below</p>
</div>
</div>
<div class="mt-3 text-sm text-blue-700">
<strong>Best Practice:</strong> Include 3-5 complete RFP responses with both questions and detailed answers for optimal AI accuracy.
</div>
</div>
</div>
</div>
<!-- Upload Area -->
<div class="bg-white rounded-2xl border-2 border-dashed border-slate-300 hover:border-blue-400 transition-colors duration-300 overflow-hidden">
<div
class="relative p-12 text-center {dragActive ? 'bg-blue-50' : 'bg-gray-50'}"
on:drop={handleDrop}
on:dragover={handleDragOver}
on:dragleave={handleDragLeave}
>
<input
type="file"
multiple
accept=".pdf,.docx,.doc,.txt"
on:change={handleFileUpload}
class="absolute inset-0 opacity-0 cursor-pointer"
/>
{#if isProcessing}
<div class="flex flex-col items-center space-y-4">
<div class="w-16 h-16 border-4 border-blue-500 border-t-transparent rounded-full animate-spin"></div>
<p class="text-blue-600 font-semibold">{processingStatus}</p>
</div>
{:else}
<div class="flex flex-col items-center space-y-4">
<div class="w-20 h-20 bg-gradient-to-r from-blue-500 to-indigo-600 rounded-2xl flex items-center justify-center text-white text-4xl">
πŸ“
</div>
<div>
<h3 class="text-2xl font-bold text-gray-800 mb-2">Upload Previous RFPs</h3>
<p class="text-gray-600 mb-4">Drop your RFP documents here or click to browse</p>
<p class="text-sm text-gray-500">Supports PDF, DOCX, DOC, and TXT files</p>
</div>
</div>
{/if}
</div>
</div>
<!-- Folder Instructions -->
<div class="bg-gradient-to-r from-green-50 to-emerald-50 rounded-2xl p-6 border border-green-200">
<div class="flex items-center space-x-3 mb-3">
<div class="w-8 h-8 bg-green-500 rounded-lg flex items-center justify-center text-white text-lg">
πŸ“‚
</div>
<h3 class="text-lg font-bold text-green-900">Alternative: Use Local Folder</h3>
</div>
<p class="text-green-800 mb-3">
For better organization and accuracy, you can add your RFP documents directly to the folder:
</p>
<div class="bg-white rounded-lg p-4 border border-green-200">
<code class="text-sm text-green-700 font-mono break-all">
{folderPath}
</code>
</div>
<p class="text-sm text-green-700 mt-2">
The system will automatically detect and analyze documents in this folder for AI reference.
</p>
</div>
<!-- Document Analysis Results -->
{#if $previousRfps.length > 0}
<div class="bg-white rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
<div class="bg-gradient-to-r from-gray-800 to-gray-900 p-6">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-3">
<div class="w-10 h-10 bg-white rounded-lg flex items-center justify-center text-gray-800 text-xl">
πŸ“Š
</div>
<div>
<h3 class="text-xl font-bold text-white">Document Analysis</h3>
<p class="text-gray-300">{$previousRfps.length} documents analyzed for AI accuracy</p>
</div>
</div>
<button
on:click={proceedToNextStep}
class="bg-gradient-to-r from-green-500 to-emerald-600 text-white px-6 py-3 rounded-xl font-semibold hover:from-green-600 hover:to-emerald-700 transition-all duration-300 shadow-lg"
>
Continue to Questions β†’
</button>
</div>
</div>
<div class="p-6 space-y-4">
{#each $previousRfps as doc, index}
<div class="border border-gray-200 rounded-xl p-4 hover:shadow-lg transition-shadow">
<div class="flex items-start justify-between">
<div class="flex-1">
<div class="flex items-center space-x-3 mb-3">
<div class="w-8 h-8 bg-blue-100 rounded-lg flex items-center justify-center text-blue-600 text-sm font-bold">
{index + 1}
</div>
<h4 class="font-semibold text-gray-800">{doc.name}</h4>
<span class="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium border {getQualityColor(doc.quality)}">
{doc.quality} Quality
</span>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-3 text-sm">
<div>
<span class="text-gray-500">Words:</span>
<span class="font-semibold text-gray-800">{doc.wordCount?.toLocaleString()}</span>
</div>
<div>
<span class="text-gray-500">Pages:</span>
<span class="font-semibold text-gray-800">{doc.pageCount}</span>
</div>
<div>
<span class="text-gray-500">Size:</span>
<span class="font-semibold text-gray-800">{(doc.size / 1024 / 1024).toFixed(1)} MB</span>
</div>
<div>
<span class="text-gray-500">Score:</span>
<span class="font-semibold text-gray-800">{analysisResults[index]?.score || 'N/A'}/100</span>
</div>
</div>
{#if doc.keyTopics && doc.keyTopics.length > 0}
<div class="flex flex-wrap gap-2 mb-3">
<span class="text-sm text-gray-500">Topics:</span>
{#each doc.keyTopics as topic}
<span class="inline-flex items-center px-2 py-1 bg-blue-100 text-blue-800 text-xs rounded-full">
{topic}
</span>
{/each}
</div>
{/if}
{#if analysisResults[index]?.recommendations}
<div class="text-sm text-gray-600">
<strong>AI Recommendation:</strong> {analysisResults[index].recommendations[0]}
</div>
{/if}
</div>
<button
on:click={() => removeDocument(doc.id)}
class="ml-4 w-8 h-8 bg-red-100 hover:bg-red-200 rounded-lg flex items-center justify-center text-red-600 transition-colors"
title="Remove document"
>
Γ—
</button>
</div>
</div>
{/each}
</div>
</div>
{/if}
<!-- Accuracy Tips -->
<div class="bg-gradient-to-r from-purple-50 to-pink-50 rounded-2xl p-6 border border-purple-200">
<div class="flex items-start space-x-4">
<div class="w-12 h-12 bg-purple-500 rounded-xl flex items-center justify-center text-white text-2xl">
🎯
</div>
<div>
<h3 class="text-lg font-bold text-purple-900 mb-3">Maximizing AI Accuracy</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm text-purple-800">
<div>
<h4 class="font-semibold mb-2">βœ… Best Documents Include:</h4>
<ul class="space-y-1 text-purple-700">
<li>β€’ Complete question-answer pairs</li>
<li>β€’ Technical specifications</li>
<li>β€’ Company methodologies</li>
<li>β€’ Previous winning proposals</li>
</ul>
</div>
<div>
<h4 class="font-semibold mb-2">⚑ For Optimal Results:</h4>
<ul class="space-y-1 text-purple-700">
<li>β€’ Upload 3-5 comprehensive RFPs</li>
<li>β€’ Include recent proposals (last 2 years)</li>
<li>β€’ Ensure documents are well-formatted</li>
<li>β€’ Mix different industry sectors</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>