Files
digicraft-fe/pages/XRayPage.tsx
Fahri Can Seçer 6e3bee17ef
Some checks failed
Deploy Frontend / deploy (push) Has been cancelled
main
2026-02-05 01:34:13 +03:00

213 lines
12 KiB
TypeScript

import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Sparkles, ArrowRight, Activity, Copy, CheckCircle, AlertTriangle, ScanEye } from 'lucide-react';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
const XRayPage: React.FC = () => {
const { t } = useTranslation();
const navigate = useNavigate();
const [url, setUrl] = useState('');
const [loading, setLoading] = useState(false);
const [result, setResult] = useState<any>(null);
const [error, setError] = useState('');
const [copied, setCopied] = useState(false);
// Mock result for dev preview if needed, but we connect to real API
const handleAnalyze = async () => {
if (!url) return;
setLoading(true);
setError('');
setResult(null);
try {
const response = await axios.post('/api/xray', { url }, {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
});
setResult(response.data);
} catch (err: any) {
console.error(err);
setError(err.response?.data?.error || 'Failed to analyze. Please check the URL and try again.');
} finally {
setLoading(false);
}
};
const copyPrompt = () => {
if (result?.analysis?.superiorPrompt) {
navigator.clipboard.writeText(result.analysis.superiorPrompt);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
};
return (
<div className="min-h-screen bg-stone-50 p-8 text-stone-900 font-sans">
<div className="max-w-6xl mx-auto space-y-12">
{/* Header Section */}
<div className="text-center space-y-4">
<div className="inline-flex items-center justify-center p-3 bg-indigo-100 rounded-full mb-4">
<ScanEye className="w-8 h-8 text-indigo-600" />
</div>
<h1 className="text-4xl font-serif font-bold tracking-tight text-stone-900">
Competitor X-Ray
</h1>
<p className="text-lg text-stone-500 max-w-2xl mx-auto">
Paste any Etsy or Pinterest product URL. Our AI will deconstruct its success formula and generate a superior prompt for you.
</p>
</div>
{/* Input Section */}
<div className="bg-white/80 backdrop-blur-xl rounded-2xl shadow-xl border border-stone-200 p-2 flex items-center max-w-3xl mx-auto transition-all focus-within:ring-4 ring-indigo-500/10">
<input
type="text"
placeholder="Paste Etsy or Pinterest URL here..."
className="flex-1 bg-transparent border-none text-lg px-6 py-4 focus:ring-0 placeholder:text-stone-400"
value={url}
onChange={(e) => setUrl(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && handleAnalyze()}
/>
<button
onClick={handleAnalyze}
disabled={loading || !url}
className={`
px-8 py-4 rounded-xl font-medium text-white shadow-lg transition-all flex items-center gap-2
${loading || !url ? 'bg-stone-300 cursor-not-allowed' : 'bg-indigo-600 hover:bg-indigo-700 hover:shadow-indigo-500/30'}
`}
>
{loading ? (
<>Running X-Ray...</>
) : (
<>Analyze <ArrowRight className="w-5 h-5" /></>
)}
</button>
</div>
{error && (
<div className="max-w-3xl mx-auto bg-red-50 text-red-600 p-4 rounded-xl border border-red-100 flex items-center gap-3">
<AlertTriangle className="w-5 h-5" />
{error}
</div>
)}
{/* Results Section */}
{result && (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 animate-in fade-in slide-in-from-bottom-8 duration-700">
{/* Left: Competitor Analysis */}
<div className="space-y-6">
<div className="bg-white rounded-2xl shadow-sm border border-stone-100 overflow-hidden">
<div className="aspect-[4/3] bg-stone-100 relative overflow-hidden">
<img
src={result.metadata.image}
alt="Competitor"
className="w-full h-full object-cover transform hover:scale-105 transition-transform duration-700"
/>
<div className="absolute top-4 left-4 bg-black/70 backdrop-blur-md text-white px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider">
Competitor Asset
</div>
</div>
<div className="p-6">
<h3 className="text-xl font-bold font-serif mb-2 line-clamp-2">{result.metadata.title}</h3>
<p className="text-stone-500 text-sm line-clamp-3 mb-4">{result.metadata.description}</p>
<div className="space-y-4">
<div>
<h4 className="text-xs font-bold text-stone-400 uppercase tracking-wider mb-2">Visual DNA Detected</h4>
<div className="flex flex-wrap gap-2">
{result.analysis.visualDna?.map((tag: string, i: number) => (
<span key={i} className="px-3 py-1 bg-stone-100 text-stone-600 rounded-full text-xs font-medium border border-stone-200">
{tag}
</span>
))}
</div>
</div>
<div>
<h4 className="text-xs font-bold text-red-400 uppercase tracking-wider mb-2">Identified Weaknesses (Sentiment Gap)</h4>
<div className="bg-red-50/50 p-4 rounded-xl border border-red-100 text-sm text-stone-700 italic">
"{result.analysis.sentimentGap}"
</div>
</div>
</div>
</div>
</div>
</div>
{/* Right: The Solution (Superior Prompt) */}
<div className="space-y-6">
<div className="bg-indigo-900 text-white rounded-2xl shadow-xl overflow-hidden relative">
{/* Decorative background glow */}
<div className="absolute top-0 right-0 w-64 h-64 bg-indigo-500/20 blur-3xl rounded-full translate-x-1/2 -translate-y-1/2"></div>
<div className="p-8 relative z-10">
<div className="flex items-center gap-3 mb-6">
<div className="p-2 bg-indigo-500/20 rounded-lg">
<Sparkles className="w-6 h-6 text-indigo-300" />
</div>
<div>
<h3 className="text-2xl font-serif font-bold">Superior Formula</h3>
<p className="text-indigo-200 text-sm">Optimized for high-conversion & aesthetics</p>
</div>
</div>
<div className="bg-black/30 backdrop-blur-sm p-6 rounded-xl border border-white/10 relative group">
<p className="font-mono text-sm text-indigo-100 leading-relaxed">
{result.analysis.superiorPrompt}
</p>
<button
onClick={copyPrompt}
className="absolute top-4 right-4 p-2 bg-white/10 hover:bg-white/20 rounded-lg transition-colors text-white"
title="Copy Prompt"
>
{copied ? <CheckCircle className="w-5 h-5 text-green-400" /> : <Copy className="w-5 h-5" />}
</button>
</div>
<div className="mt-8">
<h4 className="text-xs font-bold text-indigo-300 uppercase tracking-wider mb-3">Why This Wins</h4>
<div className="space-y-3">
<p className="text-sm text-indigo-100/80 leading-relaxed border-l-2 border-indigo-500 pl-4">
{result.analysis.gapAnalysis}
</p>
</div>
</div>
</div>
<div className="bg-indigo-950/50 p-4 flex justify-between items-center border-t border-white/10">
<span className="text-xs text-indigo-400 font-medium">Ready to dominate?</span>
<div className="flex gap-3">
<button
onClick={() => navigate('/', { state: { prompt: result.analysis.superiorPrompt } })} // Assuming Home takes state
className="px-4 py-2 bg-white text-indigo-900 rounded-lg text-sm font-bold hover:bg-indigo-50 transition-colors flex items-center gap-2"
>
Generate Asset <ArrowRight className="w-4 h-4" />
</button>
</div>
</div>
</div>
{/* Pro Tip */}
<div className="bg-yellow-50 border border-yellow-100 rounded-xl p-4 flex items-start gap-3">
<Activity className="w-5 h-5 text-yellow-600 mt-0.5" />
<div>
<h4 className="font-bold text-yellow-800 text-sm">Pro Tip</h4>
<p className="text-xs text-yellow-700 mt-1">
Use this prompt in the "Analyst" mode for best results. Consider generating 4 variations to test different lighting setups.
</p>
</div>
</div>
</div>
</div>
)}
</div>
</div>
);
};
export default XRayPage;