Files
BrainWind/app/src/components/SaveModuleDialog.tsx
T

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>
);
};