Files
digicraft-fe/components/ProcessGuideGenerator.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

138 lines
7.4 KiB
TypeScript

import React, { useRef, useState, forwardRef, useImperativeHandle } from 'react';
import { toPng } from 'html-to-image';
import axios from 'axios';
import { useTranslation } from 'react-i18next';
interface ProcessGuideGeneratorProps {
projectId?: string;
project?: { id: string } | null; // Alternative to projectId
onImageGenerated?: (path: string) => void;
onGenerate?: () => void; // Alias for backward compatibility
shopName?: string;
}
export interface ProcessGuideRef {
generate: () => Promise<void>;
}
export const ProcessGuideGenerator = forwardRef<ProcessGuideRef, ProcessGuideGeneratorProps>(({ projectId, project, onImageGenerated, onGenerate, shopName = "MrStitchPrintStudio" }, ref) => {
const resolvedProjectId = projectId || project?.id;
const { t } = useTranslation();
const elementRef = useRef<HTMLDivElement>(null);
const [isGenerating, setIsGenerating] = useState(false);
useImperativeHandle(ref, () => ({
generate: handleGenerate
}));
const handleGenerate = async () => {
if (!elementRef.current) return;
setIsGenerating(true);
try {
// Give fonts time to load visually if needed, though usually not an issue with simple fonts
const dataUrl = await toPng(elementRef.current, { cacheBust: true, pixelRatio: 1 });
// Upload to server
const response = await axios.post(`/api/projects/${projectId}/assets/upload`, {
file: dataUrl,
type: 'mockup', // Treated as mockup
folder: 'mockups',
filename: `process_guide_${Date.now()}.png`
}, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
});
if (response.data.success) {
onImageGenerated(response.data.asset.path);
}
} catch (err) {
console.error('Failed to generate process guide:', err);
throw err; // Re-throw to let parent know
} finally {
setIsGenerating(false);
}
};
return (
<div className="relative overflow-hidden w-[500px] h-[500px] bg-white">
{/* This container is what gets captured. It must be visible in DOM but can be hidden by parent overflow/opacity. */}
{/* We strictly render ONLY the capture content here. Extra UI is removed. */}
<div
ref={elementRef}
className="w-[500px] h-[500px] bg-[#F5EBE0] text-[#4A3B32] flex flex-col items-center justify-between p-12 shrink-0"
style={{ fontFamily: 'Inter, sans-serif' }}
>
{/* HEADER */}
<h1 className="text-4xl font-bold uppercase tracking-wide mt-4">HOW IT WORKS</h1>
{/* STEPS ROW */}
<div className="flex justify-between w-full mt-8">
{/* STEP 1 */}
<div className="flex flex-col items-center text-center w-1/3 px-2">
<div className="mb-4">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-16 h-16">
<path strokeLinecap="round" strokeLinejoin="round" d="M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 0 0-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 0 0-16.536-1.84M7.5 14.25 5.106 5.272M6 20.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Zm12.75 0a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z" />
</svg>
</div>
<h3 className="font-bold text-lg mb-1">ADD TO CART</h3>
<p className="text-xs leading-tight opacity-80">Select your digital product and add it to your cart.</p>
</div>
{/* STEP 2 */}
<div className="flex flex-col items-center text-center w-1/3 px-2 border-l border-r border-[#4A3B32]/10">
<div className="mb-4">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-16 h-16">
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12c0 1.268-.63 2.39-1.593 3.068a3.745 3.745 0 0 1-1.043 3.296 3.745 3.745 0 0 1-3.296 1.043A3.745 3.745 0 0 1 12 21c-1.268 0-2.39-.63-3.068-1.593a3.746 3.746 0 0 1-3.296-1.043 3.745 3.745 0 0 1-1.043-3.296A3.745 3.745 0 0 1 3 12c0-1.268.63-2.39 1.593-3.068a3.745 3.745 0 0 1 1.043-3.296 3.746 3.746 0 0 1 3.296-1.043A3.746 3.746 0 0 1 12 3c1.268 0 2.39.63 3.068 1.593a3.746 3.746 0 0 1 3.296 1.043 3.746 3.746 0 0 1 1.043 3.296A3.745 3.745 0 0 1 21 12Z" />
</svg>
</div>
<h3 className="font-bold text-lg mb-1">CHECKOUT</h3>
<p className="text-xs leading-tight opacity-80">Complete payment to securely confirm your purchase.</p>
</div>
{/* STEP 3 */}
<div className="flex flex-col items-center text-center w-1/3 px-2">
<div className="mb-4">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-16 h-16">
<path strokeLinecap="round" strokeLinejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
</svg>
</div>
<h3 className="font-bold text-lg mb-1">DOWNLOAD</h3>
<p className="text-xs leading-tight opacity-80">Access your download link in the receipt email.</p>
</div>
</div>
{/* IMPORTANT NOTICE */}
<div className="w-full text-left mt-8">
<h4 className="font-bold uppercase text-sm mb-1">IMPORTANT:</h4>
<p className="text-xs"> This is an <span className="font-bold">INSTANT DOWNLOAD</span>. No physical items will be shipped or sent.</p>
</div>
{/* FOOTER */}
<div className="relative mt-auto w-full">
{/* Speech Bubble effect */}
<div className="bg-white/50 p-6 rounded-2xl relative">
<h4 className="font-bold text-sm mb-2">Thank you for stopping by!</h4>
<p className="text-[10px] leading-relaxed opacity-90">
Our goal is to create products that inspire, uplift, and add a touch of positivity to your life.
We hope you find joy in our products, and if you have any questions or feedback, we'd love to hear from you!
</p>
{/* Triangle */}
<div className="absolute -bottom-3 left-8 w-0 h-0 border-l-[10px] border-l-transparent border-t-[15px] border-t-white/50 border-r-[10px] border-r-transparent"></div>
</div>
<div className="mt-6 ml-8 font-bold text-sm opacity-80">
{shopName}
</div>
</div>
</div>
</div>
);
});
ProcessGuideGenerator.displayName = 'ProcessGuideGenerator';