Files
promptstory/components/StepResult.tsx
2026-02-15 19:52:28 +01:00

192 lines
8.7 KiB
TypeScript

import React, { useState } from 'react';
import { GeneratedContent, WizardState } from '../types';
import { Copy, Check, Instagram, Image as ImageIcon, MessageSquare, Edit2, RefreshCw, X } from 'lucide-react';
import TripMap from './TripMap';
import { UI_TEXT } from '../_EDITABLE_CONFIG/ui_text';
interface ExtendedStepResultProps {
content: GeneratedContent;
onRegenerate: (slideCount: number, feedback: string) => void;
isRegenerating: boolean;
tripData?: WizardState['tripData'];
eventType?: WizardState['eventType'];
}
const StepResult: React.FC<ExtendedStepResultProps> = ({ content, onRegenerate, isRegenerating, tripData, eventType }) => {
const [copiedSection, setCopiedSection] = useState<string | null>(null);
const [copiedSlideIndex, setCopiedSlideIndex] = useState<number | null>(null);
const [isEditing, setIsEditing] = useState(false);
const [slideCount, setSlideCount] = useState(content.slides.length || 12);
const [feedback, setFeedback] = useState("");
const copyToClipboard = (text: string, sectionId: string) => {
navigator.clipboard.writeText(text);
setCopiedSection(sectionId);
setTimeout(() => setCopiedSection(null), 2000);
};
const copySlideText = (text: string, index: number) => {
navigator.clipboard.writeText(text);
setCopiedSlideIndex(index);
setTimeout(() => setCopiedSlideIndex(null), 2000);
};
const handleApplyChanges = () => {
onRegenerate(slideCount, feedback);
setIsEditing(false);
};
return (
<div className="space-y-12 animate-fade-in pb-20 relative">
<div className="text-center max-w-2xl mx-auto relative">
<h2 className="text-4xl font-bold tracking-tight text-gray-900 mb-3">{UI_TEXT.stepResult.title}</h2>
<p className="text-gray-500 text-lg mb-6">{UI_TEXT.stepResult.subtitle}</p>
{!isEditing && !isRegenerating && (
<button
onClick={() => setIsEditing(true)}
className="inline-flex items-center space-x-2 text-sm font-bold text-gray-600 bg-gray-100 hover:bg-gray-200 px-5 py-2.5 rounded-full transition-colors"
>
<Edit2 size={16} />
<span>{UI_TEXT.stepResult.editBtn}</span>
</button>
)}
</div>
{(isEditing || isRegenerating) && (
<div className="bg-white border-2 border-[#EA4420]/20 rounded-xl p-6 shadow-sm mb-10 animate-fade-in relative overflow-hidden">
{isRegenerating && (
<div className="absolute inset-0 bg-white/80 z-10 flex flex-col items-center justify-center backdrop-blur-[1px]">
<RefreshCw size={32} className="text-[#EA4420] animate-spin mb-3" />
<p className="font-bold text-gray-800">{UI_TEXT.stepResult.editPanel.regenerating}</p>
</div>
)}
<div className="flex justify-between items-start mb-6">
<h3 className="text-xl font-bold text-gray-900 flex items-center gap-2">
<Edit2 size={20} className="text-[#EA4420]" />
{UI_TEXT.stepResult.editPanel.title}
</h3>
{!isRegenerating && (
<button onClick={() => setIsEditing(false)} className="text-gray-400 hover:text-gray-600">
<X size={24} />
</button>
)}
</div>
<div className="space-y-6">
<div>
<label className="flex justify-between text-sm font-bold text-gray-700 mb-3">
<span>{UI_TEXT.stepResult.editPanel.slidesLabel}</span>
<span className="text-[#EA4420]">{slideCount}</span>
</label>
<input
type="range"
min="3"
max="20"
value={slideCount}
onChange={(e) => setSlideCount(parseInt(e.target.value))}
className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-[#EA4420]"
/>
<div className="flex justify-between text-xs text-gray-400 mt-2 font-medium">
<span>3 (Minimum)</span>
<span>20 (Maksimum)</span>
</div>
</div>
<div>
<label className="block text-sm font-bold text-gray-700 mb-2">{UI_TEXT.stepResult.editPanel.feedbackLabel}</label>
<textarea
value={feedback}
onChange={(e) => setFeedback(e.target.value)}
placeholder={UI_TEXT.stepResult.editPanel.feedbackPlaceholder}
rows={3}
className="w-full border border-gray-200 rounded-md p-3 text-sm focus:ring-1 focus:ring-[#EA4420] focus:border-[#EA4420] outline-none"
/>
</div>
<div className="flex justify-end pt-2">
<button
onClick={handleApplyChanges}
className="bg-[#EA4420] text-white px-6 py-3 rounded-md font-bold hover:bg-[#d63b1a] transition-colors flex items-center gap-2"
>
<RefreshCw size={18} />
{UI_TEXT.stepResult.editPanel.applyBtn}
</button>
</div>
</div>
</div>
)}
{/* MAPA WYŚWIETLA SIĘ TYLKO DLA WYCIECZEK */}
{eventType === 'trip' && tripData && tripData.startPoint && (
<TripMap tripData={tripData} />
)}
<div className="bg-white rounded-md border border-gray-200 overflow-hidden">
<div className="bg-gray-50 px-8 py-5 border-b border-gray-200 flex justify-between items-center">
<div className="flex items-center space-x-3 text-gray-900">
<MessageSquare size={20} className="text-[#EA4420]" />
<span className="font-bold">{UI_TEXT.stepResult.captionTitle}</span>
</div>
<button
onClick={() => copyToClipboard(content.caption, 'caption')}
className="flex items-center space-x-2 text-sm font-semibold text-[#EA4420] hover:text-[#d63b1a] transition-colors bg-white border border-gray-200 px-4 py-2 rounded-md hover:bg-gray-50"
>
{copiedSection === 'caption' ? <Check size={16} /> : <Copy size={16} />}
<span>{copiedSection === 'caption' ? UI_TEXT.stepResult.copied : UI_TEXT.stepResult.copy}</span>
</button>
</div>
<div className="p-8 text-gray-700 whitespace-pre-wrap font-sans text-base leading-relaxed">
{content.caption}
</div>
</div>
<div>
<div className="flex items-center space-x-3 text-gray-900 mb-8 px-1">
<ImageIcon size={28} className="text-[#EA4420]" />
<h3 className="text-2xl font-bold tracking-tight">{UI_TEXT.stepResult.slidesTitle}</h3>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{content.slides.map((slide, idx) => (
<div key={idx} className="bg-white rounded-md border border-gray-200 flex flex-col h-full hover:border-[#EA4420]/30 transition-colors group">
<div className="px-6 py-4 border-b border-gray-100 bg-gray-50/50 flex justify-between items-center">
<span className="text-xs font-bold text-gray-400 uppercase tracking-widest">
Element {idx + 1}
</span>
</div>
<div className="p-6 flex-1 flex flex-col space-y-6">
<div>
<div className="flex justify-between items-start mb-2">
<span className="text-xs text-[#EA4420] uppercase font-bold tracking-wider">Nagłówek / Typ</span>
<button
onClick={() => copySlideText(slide.overlay_text, idx)}
className="text-gray-300 hover:text-[#EA4420] transition-colors"
title={UI_TEXT.stepResult.copy}
>
{copiedSlideIndex === idx ? <Check size={14} className="text-green-500" /> : <Copy size={14} />}
</button>
</div>
<p className="font-bold text-gray-900 text-xl leading-tight">"{slide.overlay_text}"</p>
</div>
<div className="pt-4 border-t border-gray-100 mt-auto">
<div className="flex items-start space-x-3 text-gray-500">
<ImageIcon size={16} className="mt-1 flex-shrink-0 text-gray-400" />
<p className="text-sm italic leading-relaxed">{slide.image_prompt}</p>
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
);
};
export default StepResult;