🚀 Auto-deploy: BrainWind atualizado em 26/08/2026 10:57:31
This commit is contained in:
@@ -19,7 +19,7 @@ import { EducationalManual } from '@/components/EducationalManual';
|
||||
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
||||
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
||||
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
||||
import { Eye, Box, Layers, ArrowUpRight, CheckCircle2, Wind } from 'lucide-react';
|
||||
import { Eye, Box, Layers, ArrowUpRight, CheckCircle2, Wind, AlertTriangle } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const conditionLabels: Record<ShelterCondition, string> = {
|
||||
@@ -41,6 +41,7 @@ const ShelterModule: React.FC = () => {
|
||||
const [backRange, setBackRange] = useState<[number, number]>([0, 75]);
|
||||
const [leftClosure, setLeftClosure] = useState(100);
|
||||
const [rightClosure, setRightClosure] = useState(100);
|
||||
const [surfaceMass, setSurfaceMass] = useState(15); // kg/m² para lona/telha leve
|
||||
const [viewMode, setViewMode] = useState<'3d' | 'elevation' | 'airflow'>('3d');
|
||||
|
||||
// Determinação automática da posição da fresta/vão a partir dos cursores (base e topo)
|
||||
@@ -100,6 +101,9 @@ const ShelterModule: React.FC = () => {
|
||||
const effAreaRoof = depth * width;
|
||||
const effAreaBack = (width * height) * (backClosure / 100);
|
||||
const effAreaSideTotal = (depth * height) * ((leftClosure + rightClosure) / 100);
|
||||
|
||||
const gravityForce = (surfaceMass * effAreaRoof * 9.81) / 1000; // in kN
|
||||
const isUpliftCritical = envelope.criticalUp.value > gravityForce;
|
||||
|
||||
const handleExportPDF = () => {
|
||||
const angleLabel = windAngle === 0 ? '0° (Frontal)' : windAngle === 45 ? '45° (Oblíquo)' : '90° (Lateral)';
|
||||
@@ -351,7 +355,7 @@ const ShelterModule: React.FC = () => {
|
||||
</div>
|
||||
<SaveModuleDialog
|
||||
moduleType="shelter"
|
||||
inputs={{ condition, depth, width, height, theta, backClosure, leftClosure, rightClosure, openingPos, windAngle }}
|
||||
inputs={{ condition, depth, width, height, theta, backClosure, leftClosure, rightClosure, openingPos, windAngle, surfaceMass }}
|
||||
/>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-5">
|
||||
@@ -476,6 +480,21 @@ const ShelterModule: React.FC = () => {
|
||||
</div>
|
||||
<Slider min={0} max={30} step={1} value={[theta]} onValueChange={(v) => setTheta(v[0])} />
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 pt-2 border-t">
|
||||
<div className="flex justify-between text-xs">
|
||||
<span>Massa Superficial (kg/m²):</span>
|
||||
<span className="font-mono font-medium">{surfaceMass} kg/m²</span>
|
||||
</div>
|
||||
<Slider min={2} max={100} step={1} value={[surfaceMass]} onValueChange={(v) => setSurfaceMass(v[0])} />
|
||||
<p className="text-[10px] text-muted-foreground mt-1">Lonas ~3kg/m², Telhas Metálicas ~10-15kg/m²</p>
|
||||
{isUpliftCritical && (
|
||||
<div className="mt-2 p-2 bg-destructive/10 border border-destructive/20 rounded text-xs text-destructive flex gap-2 items-start">
|
||||
<AlertTriangle className="w-4 h-4 shrink-0 mt-0.5" />
|
||||
<p>Alerta de Arrancamento: Força (↑) {envelope.criticalUp.value.toFixed(1)} kN > Peso ({gravityForce.toFixed(1)} kN). Exige ancoragem/estaiamento.</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user