Fixes inconsistencies discovered during audit against urt-taxonomy/: - urt_profile ENUM: Add 'lite' and 'core' profiles (was missing) - USN format: Use canonical regex from spec (was non-compliant) - USN valence encoding: Add V0 (0) and V± (±) support - USN grammar: Add Lite (URT:L:) and Core (URT:C:) formats - Dimension codes: Fix temporal (TC/TR/TH/TF), evidence (ES/EI/EC), comparative (CR-N/CR-B/CR-W/CR-S) in decisions doc - LLM contract: Full USN regex validation pattern Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
61 lines
2.4 KiB
TypeScript
61 lines
2.4 KiB
TypeScript
'use client';
|
|
|
|
import { useRouter } from 'next/navigation';
|
|
import { useCallback } from 'react';
|
|
import ScraperTest from '@/components/ScraperTest';
|
|
import { useJobs } from '@/contexts/JobsContext';
|
|
import { JobStatus } from '@/components/ScraperTest';
|
|
import Link from 'next/link';
|
|
|
|
export default function GoogleReviewsScraperPage() {
|
|
const router = useRouter();
|
|
const { addJob } = useJobs();
|
|
|
|
const handleJobsChange = useCallback((jobs: JobStatus[]) => {
|
|
// Add new jobs to context (addJob handles deduplication)
|
|
jobs.forEach(job => addJob(job));
|
|
}, [addJob]);
|
|
|
|
const handleSelectReviews = (reviews: unknown[], businessName: string, jobId: string) => {
|
|
// Navigate to analytics page for this job
|
|
router.push(`/analytics/${jobId}`);
|
|
};
|
|
|
|
return (
|
|
<div className="h-full overflow-y-auto p-6">
|
|
{/* Breadcrumb */}
|
|
<div className="max-w-4xl mx-auto mb-6">
|
|
<nav className="flex items-center gap-2 text-sm text-gray-500">
|
|
<Link href="/new" className="hover:text-blue-600 transition-colors">
|
|
New Scrape
|
|
</Link>
|
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
|
</svg>
|
|
<span className="text-gray-900 font-medium">Google Reviews</span>
|
|
</nav>
|
|
</div>
|
|
|
|
{/* Header */}
|
|
<div className="max-w-4xl mx-auto mb-6">
|
|
<div className="flex items-center gap-4">
|
|
<div className="w-14 h-14 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-xl flex items-center justify-center shadow-lg">
|
|
<svg className="w-7 h-7 text-white" viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<h1 className="text-2xl font-bold text-gray-900">Google Reviews Scraper</h1>
|
|
<p className="text-gray-500">Extract reviews from any Google Maps business listing</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<ScraperTest
|
|
onJobsChange={handleJobsChange}
|
|
onSelectReviews={handleSelectReviews}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|