Files
fabrikanabytok/apps/fabrikanabytok/components/planner/export-dialog.tsx
2025-11-28 20:48:15 +01:00

297 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client"
import { useState } from "react"
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Download, ImageIcon, FileText, Box, Loader2 } from "lucide-react"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Checkbox } from "@/components/ui/checkbox"
import { Label } from "@/components/ui/label"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { getDesignShoppingList } from "@/lib/actions/export.actions"
import { useToast } from "@/hooks/use-toast"
import { usePlannerExport } from "@/hooks/use-planner-export"
import type { Design } from "@/lib/types/planner.types"
interface ExportDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
design: Design
}
export function ExportDialog({ open, onOpenChange, design }: ExportDialogProps) {
const [loading, setLoading] = useState(false)
const [selectedAngles, setSelectedAngles] = useState<string[]>(["iso"])
const [resolution, setResolution] = useState<"hd" | "fhd" | "4k" | "8k">("fhd")
const { toast } = useToast()
// Get export functions from the hook (only works inside Canvas context)
// We'll pass the design and use a ref to access canvas
const handleImageExport = async () => {
setLoading(true)
try {
// Get canvas element
const canvas = document.querySelector("canvas")
if (!canvas) {
throw new Error("Canvas not found")
}
// Import utilities
const { captureCanvasScreenshot, downloadDataUrl, getResolutionDimensions } = await import("@/lib/utils/canvas-export")
const dimensions = getResolutionDimensions(resolution)
const dataUrl = await captureCanvasScreenshot(canvas, {
...dimensions,
format: "png",
})
// Download image
const filename = `${design.name}-${selectedAngles.join("-")}.png`
downloadDataUrl(dataUrl, filename)
toast({
title: "Sikeres exportálás",
description: "Kép sikeresen exportálva",
})
onOpenChange(false)
} catch (error: any) {
toast({
title: "Hiba",
description: error.message,
variant: "destructive",
})
} finally {
setLoading(false)
}
}
const handlePDFExport = async () => {
setLoading(true)
try {
// Get canvas and capture screenshot
const canvas = document.querySelector("canvas")
if (!canvas) {
throw new Error("Canvas not found")
}
const { captureCanvasScreenshot } = await import("@/lib/utils/canvas-export")
const dataUrl = await captureCanvasScreenshot(canvas, {
width: 1920,
height: 1080,
format: "png",
})
// Get shopping list
const shoppingList = await getDesignShoppingList(design.id)
// Generate PDF
const { generateDesignPDF, downloadPDF } = await import("@/lib/utils/pdf-generator")
const pdfBlob = await generateDesignPDF(
design,
[{ name: "3D View", dataUrl }],
shoppingList,
{
includeImages: true,
includeShoppingList: true,
includeDimensions: true,
includeMaterials: true,
includeQRCode: true,
watermark: true,
}
)
const filename = `${design.name}-Report.pdf`
downloadPDF(pdfBlob, filename)
toast({
title: "Sikeres exportálás",
description: "PDF riport sikeresen létrehozva",
})
onOpenChange(false)
} catch (error: any) {
toast({
title: "Hiba",
description: error.message,
variant: "destructive",
})
} finally {
setLoading(false)
}
}
const handle3DExport = async () => {
setLoading(true)
try {
toast({
title: "Exportálás folyamatban",
description: "3D modell előkészítése...",
})
// Note: Actual GLB export requires access to THREE.js scene
// This is a placeholder - would need scene access from Canvas
toast({
title: "Funkció fejlesztés alatt",
description: "3D modell export hamarosan elérhető",
})
onOpenChange(false)
} catch (error: any) {
toast({
title: "Hiba",
description: error.message,
variant: "destructive",
})
} finally {
setLoading(false)
}
}
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>Terv exportálása</DialogTitle>
<DialogDescription>Válassz exportálási formátumot és beállításokat</DialogDescription>
</DialogHeader>
<Tabs defaultValue="image" className="w-full">
<TabsList className="grid w-full grid-cols-3">
<TabsTrigger value="image" className="gap-2">
<ImageIcon className="w-4 h-4" />
Képek
</TabsTrigger>
<TabsTrigger value="pdf" className="gap-2">
<FileText className="w-4 h-4" />
PDF Riport
</TabsTrigger>
<TabsTrigger value="3d" className="gap-2">
<Box className="w-4 h-4" />
3D Modell
</TabsTrigger>
</TabsList>
<TabsContent value="image" className="space-y-4">
<div className="space-y-3">
<div>
<Label className="mb-2 block">Felbontás:</Label>
<Select value={resolution} onValueChange={(v: any) => setResolution(v)}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="hd">HD (1280×720)</SelectItem>
<SelectItem value="fhd">Full HD (1920×1080)</SelectItem>
<SelectItem value="4k">4K (3840×2160)</SelectItem>
<SelectItem value="8k">8K (7680×4320)</SelectItem>
</SelectContent>
</Select>
</div>
<Label>Válassz nézeteket:</Label>
<div className="space-y-2">
{[
{ value: "front", label: "Elölnézet" },
{ value: "back", label: "Hátulnézet" },
{ value: "left", label: "Bal oldal" },
{ value: "right", label: "Jobb oldal" },
{ value: "top", label: "Felülnézet" },
{ value: "iso", label: "Izometrikus (3D)" },
].map((angle) => (
<div key={angle.value} className="flex items-center gap-2">
<Checkbox
id={angle.value}
checked={selectedAngles.includes(angle.value)}
onCheckedChange={(checked) => {
setSelectedAngles(
checked ? [...selectedAngles, angle.value] : selectedAngles.filter((a) => a !== angle.value),
)
}}
/>
<Label htmlFor={angle.value} className="cursor-pointer">
{angle.label}
</Label>
</div>
))}
</div>
</div>
<Button onClick={handleImageExport} disabled={loading || selectedAngles.length === 0} className="w-full">
{loading ? (
<>
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
Exportálás...
</>
) : (
<>
<Download className="w-4 h-4 mr-2" />
Kép letöltése ({resolution.toUpperCase()})
</>
)}
</Button>
</TabsContent>
<TabsContent value="pdf" className="space-y-4">
<div className="space-y-2 text-sm text-muted-foreground">
<p>A PDF riport tartalmazza:</p>
<ul className="list-disc list-inside space-y-1 ml-2">
<li>Terv képek (több nézetből)</li>
<li>Bevásárló lista termékekkel és árakkal</li>
<li>Szoba méretek és specifikációk</li>
<li>QR kód a terv megosztásához</li>
</ul>
</div>
<Button onClick={handlePDFExport} disabled={loading} className="w-full">
{loading ? (
<>
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
Exportálás...
</>
) : (
<>
<Download className="w-4 h-4 mr-2" />
PDF letöltése
</>
)}
</Button>
</TabsContent>
<TabsContent value="3d" className="space-y-4">
<div className="rounded-lg bg-amber-500/10 border border-amber-500/20 p-4">
<p className="text-sm text-amber-600 font-medium">Prémium funkció</p>
<p className="text-sm text-muted-foreground mt-1">
3D modell exportálásához prémium előfizetés szükséges
</p>
</div>
<div className="space-y-2 text-sm text-muted-foreground">
<p>A .glb fájl importálható:</p>
<ul className="list-disc list-inside space-y-1 ml-2">
<li>Blender</li>
<li>SketchUp</li>
<li>AutoCAD</li>
<li>És más 3D szoftverek</li>
</ul>
</div>
<Button onClick={handle3DExport} disabled={loading} className="w-full">
{loading ? (
<>
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
Exportálás...
</>
) : (
<>
<Download className="w-4 h-4 mr-2" />
.glb fájl letöltése
</>
)}
</Button>
</TabsContent>
</Tabs>
</DialogContent>
</Dialog>
)
}