122 lines
4.0 KiB
TypeScript
122 lines
4.0 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { Button } from './ui/button';
|
|
import { Input } from './ui/input';
|
|
import { Save, FileJson, FileBox } from 'lucide-react';
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from './ui/dialog';
|
|
import { useProjects } from '../lib/hooks/useProjects';
|
|
import { useWindStore } from '../store/appStore';
|
|
|
|
interface SaveModuleDialogProps {
|
|
moduleType: 'galpao' | 'cilindro' | 'vault' | 'dome' | 'sign' | 'isolated-roof' | 'bar' | 'bridge' | 'dynamics' | 'piperack';
|
|
inputs: Record<string, unknown>;
|
|
triggerButton?: React.ReactNode;
|
|
}
|
|
|
|
export const SaveModuleDialog: React.FC<SaveModuleDialogProps> = ({ moduleType, inputs, triggerButton }) => {
|
|
const { save } = useProjects();
|
|
const windStore = useWindStore();
|
|
const [open, setOpen] = useState(false);
|
|
const [name, setName] = useState('');
|
|
const [type, setType] = useState<'projeto' | 'template'>('projeto');
|
|
|
|
// Gera um nome sugerido ao abrir
|
|
React.useEffect(() => {
|
|
if (open && !name) {
|
|
const date = new Date().toLocaleDateString('pt-BR').replace(/\//g, '');
|
|
const prefix = type === 'projeto' ? 'PRJ' : 'TPL';
|
|
const modName = moduleType.charAt(0).toUpperCase() + moduleType.slice(1);
|
|
setName(`${prefix}-${modName}-${date}`);
|
|
}
|
|
}, [open, type, moduleType, name]);
|
|
|
|
const handleSave = async () => {
|
|
if (!name.trim()) return;
|
|
|
|
const windData = type === 'projeto' ? {
|
|
v0: windStore.v0,
|
|
s1: windStore.s1,
|
|
s3: windStore.s3,
|
|
s3Group: windStore.s3Group,
|
|
terrainCategory: windStore.terrainCategory,
|
|
largestDimension: windStore.largestDimension,
|
|
heightZ: windStore.heightZ,
|
|
} : undefined;
|
|
|
|
await save({
|
|
name,
|
|
type,
|
|
module: moduleType,
|
|
inputs,
|
|
windData,
|
|
createdAt: Date.now(),
|
|
updatedAt: Date.now(),
|
|
});
|
|
|
|
setOpen(false);
|
|
};
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={setOpen}>
|
|
<DialogTrigger asChild>
|
|
{triggerButton || (
|
|
<Button variant="outline" size="sm" className="gap-2">
|
|
<Save className="h-4 w-4" />
|
|
Salvar
|
|
</Button>
|
|
)}
|
|
</DialogTrigger>
|
|
<DialogContent className="sm:max-w-[425px]">
|
|
<DialogHeader>
|
|
<DialogTitle>Salvar Módulo</DialogTitle>
|
|
<DialogDescription>
|
|
Escolha como deseja salvar este módulo.
|
|
Projetos incluem os dados de vento atuais. Templates salvam apenas a geometria da estrutura.
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<div className="grid gap-4 py-4">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<Button
|
|
variant={type === 'projeto' ? 'default' : 'outline'}
|
|
className="h-20 flex flex-col gap-2"
|
|
onClick={() => setType('projeto')}
|
|
>
|
|
<FileBox className="h-6 w-6" />
|
|
Projeto Completo
|
|
</Button>
|
|
<Button
|
|
variant={type === 'template' ? 'default' : 'outline'}
|
|
className="h-20 flex flex-col gap-2"
|
|
onClick={() => setType('template')}
|
|
>
|
|
<FileJson className="h-6 w-6" />
|
|
Template (Geometria)
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="grid gap-2">
|
|
<label htmlFor="name" className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">Nome do Arquivo</label>
|
|
<Input
|
|
id="name"
|
|
value={name}
|
|
onChange={(e) => setName(e.target.value)}
|
|
placeholder="Digite um nome para identificar..."
|
|
/>
|
|
</div>
|
|
</div>
|
|
<DialogFooter>
|
|
<Button variant="ghost" onClick={() => setOpen(false)}>Cancelar</Button>
|
|
<Button onClick={handleSave} disabled={!name.trim()}>Salvar {type === 'projeto' ? 'Projeto' : 'Template'}</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
};
|