| import { useEffect, useState } from "react"; |
| import { useParams } from "react-router-dom"; |
| import { Download } from "lucide-react"; |
| import { API_BASE } from "../../api/client"; |
|
|
| interface ShareData { |
| output_filename: string; |
| segment_filename: string | null; |
| created_at: string; |
| } |
|
|
| export default function SharedView() { |
| const { shareId } = useParams<{ shareId: string }>(); |
| const [imageUrl, setImageUrl] = useState<string | null>(null); |
| const [error, setError] = useState<string | null>(null); |
| const [loading, setLoading] = useState(true); |
|
|
| useEffect(() => { |
| if (!shareId) { |
| setError("ID de sesión inválido"); |
| setLoading(false); |
| return; |
| } |
| fetch(`${API_BASE}/api/share/${shareId}`) |
| .then((res) => { |
| if (!res.ok) throw new Error("Sesión compartida no encontrada o expirada"); |
| return res.json() as Promise<ShareData>; |
| }) |
| .then((data) => { |
| setImageUrl(`${API_BASE}/seg/image/${data.output_filename}`); |
| }) |
| .catch((err: Error) => setError(err.message)) |
| .finally(() => setLoading(false)); |
| }, [shareId]); |
|
|
| const handleDownload = async () => { |
| if (!imageUrl) return; |
| const res = await fetch(imageUrl); |
| const blob = await res.blob(); |
| const url = URL.createObjectURL(blob); |
| const a = document.createElement("a"); |
| a.href = url; |
| a.download = `hyper-reality-${shareId}.jpg`; |
| document.body.appendChild(a); |
| a.click(); |
| document.body.removeChild(a); |
| URL.revokeObjectURL(url); |
| }; |
|
|
| if (loading) { |
| return ( |
| <div className="flex items-center justify-center h-screen bg-gray-950 text-white text-sm"> |
| Cargando diseño compartido... |
| </div> |
| ); |
| } |
|
|
| if (error) { |
| return ( |
| <div className="flex flex-col items-center justify-center h-screen bg-gray-950 gap-3"> |
| <p className="text-red-400 text-sm">{error}</p> |
| <p className="text-gray-500 text-xs"> |
| Este enlace puede haber expirado. Los diseños compartidos se mantienen mientras el servidor esté activo. |
| </p> |
| </div> |
| ); |
| } |
|
|
| return ( |
| <div className="flex flex-col h-screen bg-gray-950"> |
| {/* Header */} |
| <div className="flex items-center justify-between px-5 py-3 bg-white shadow-sm shrink-0"> |
| <span className="text-[#0047AB] font-bold text-base tracking-tight"> |
| Hyper Reality Visualizer |
| </span> |
| <button |
| onClick={handleDownload} |
| className="flex items-center gap-2 px-4 py-2 bg-[#0047AB] text-white rounded-full text-sm font-medium hover:bg-[#003a94] transition-colors" |
| > |
| <Download className="w-4 h-4" /> |
| Descargar |
| </button> |
| </div> |
| |
| {/* Image */} |
| <div className="flex-1 flex items-center justify-center p-6 min-h-0"> |
| {imageUrl && ( |
| <img |
| src={imageUrl} |
| alt="Diseño de habitación compartido" |
| className="max-h-full max-w-full object-contain rounded-xl shadow-2xl" |
| /> |
| )} |
| </div> |
| |
| {/* Footer */} |
| <div className="text-center py-3 text-gray-500 text-xs shrink-0"> |
| Diseñado con{" "} |
| <a |
| href="https://hyperrealitycompany.com" |
| target="_blank" |
| rel="noopener noreferrer" |
| className="text-[#4a7fd4] hover:underline" |
| > |
| Hyper Reality Visualizer |
| </a> |
| </div> |
| </div> |
| ); |
| } |
|
|