🚀 Auto-deploy: BrainWind atualizado em 01/09/2026 16:55:27
This commit is contained in:
@@ -0,0 +1,35 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { create } from 'zustand';
|
||||||
|
|
||||||
|
interface PersistentStore {
|
||||||
|
data: Record<string, any>;
|
||||||
|
setValue: (key: string, value: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const usePersistentStore = create<PersistentStore>((set) => ({
|
||||||
|
data: {},
|
||||||
|
setValue: (key, value) => set((state) => ({ data: { ...state.data, [key]: value } })),
|
||||||
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook para substituir o useState e manter o valor salvo globalmente na memória (Zustand)
|
||||||
|
* durante a navegação entre os componentes.
|
||||||
|
*/
|
||||||
|
export function usePersistentState<T>(key: string, initialValue: T): [T, (val: T | ((prev: T) => T)) => void] {
|
||||||
|
const storeValue = usePersistentStore((s) => s.data[key]);
|
||||||
|
const setValue = usePersistentStore((s) => s.setValue);
|
||||||
|
|
||||||
|
// Como o store não tem o valor inicial no momento da criação, precisamos lidar com isso.
|
||||||
|
// Se o valor estiver no store, usamos ele. Senão, usamos initialValue.
|
||||||
|
const value = storeValue !== undefined ? storeValue : initialValue;
|
||||||
|
|
||||||
|
const setter = (newVal: T | ((prev: T) => T)) => {
|
||||||
|
if (typeof newVal === 'function') {
|
||||||
|
setValue(key, (newVal as any)(value));
|
||||||
|
} else {
|
||||||
|
setValue(key, newVal);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return [value, setter];
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import { WindParametersSummary } from '@/components/WindParametersSummary';
|
|||||||
import { EducationalManual } from '@/components/EducationalManual';
|
import { EducationalManual } from '@/components/EducationalManual';
|
||||||
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
||||||
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
const BarSelectorModule: React.FC = () => {
|
const BarSelectorModule: React.FC = () => {
|
||||||
const { vk, q } = useWindStore();
|
const { vk, q } = useWindStore();
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import ExportMenu from '../components/ExportMenu';
|
|||||||
import { EducationalManual } from '@/components/EducationalManual';
|
import { EducationalManual } from '@/components/EducationalManual';
|
||||||
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
||||||
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ const BridgeModule: React.FC = () => {
|
|||||||
const [fv, setFv] = React.useState(0.6);
|
const [fv, setFv] = React.useState(0.6);
|
||||||
const [vk, setVk] = React.useState(45);
|
const [vk, setVk] = React.useState(45);
|
||||||
const [alpha, setAlpha] = React.useState(0);
|
const [alpha, setAlpha] = React.useState(0);
|
||||||
const [viewMode, setViewMode] = useState<'solid' | 'airflow'>('solid');
|
const [viewMode, setViewMode] = usePersistentState<'solid' | 'airflow'>('BridgeModule_viewMode', 'solid');
|
||||||
const [vf, setVf] = React.useState(100); // Velocidade crítica de flutter da seção
|
const [vf, setVf] = React.useState(100); // Velocidade crítica de flutter da seção
|
||||||
|
|
||||||
const classification = useMemo(
|
const classification = useMemo(
|
||||||
|
|||||||
@@ -9,12 +9,13 @@ import { EducationalManual } from '@/components/EducationalManual';
|
|||||||
import { Wind, Box } from 'lucide-react';
|
import { Wind, Box } from 'lucide-react';
|
||||||
import { Slider } from '@/components/ui/slider';
|
import { Slider } from '@/components/ui/slider';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
export default function CalcCaModule() {
|
export default function CalcCaModule() {
|
||||||
const [l1, setL1] = useState<number>(20);
|
const [l1, setL1] = usePersistentState<number>('CalcCaModule_l1', 20);
|
||||||
const [l2, setL2] = useState<number>(40);
|
const [l2, setL2] = usePersistentState<number>('CalcCaModule_l2', 40);
|
||||||
const [h, setH] = useState<number>(10);
|
const [h, setH] = usePersistentState<number>('CalcCaModule_h', 10);
|
||||||
const [viewMode, setViewMode] = useState<'solid' | 'airflow'>('solid');
|
const [viewMode, setViewMode] = usePersistentState<'solid' | 'airflow'>('CalcCaModule_viewMode', 'solid');
|
||||||
|
|
||||||
// Clamp inputs to avoid Infinity or negative values breaking the UI
|
// Clamp inputs to avoid Infinity or negative values breaking the UI
|
||||||
const safeL1 = Math.max(0.1, l1 || 1);
|
const safeL1 = Math.max(0.1, l1 || 1);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { PressureLegend } from '@/components/PressureLegend';
|
|||||||
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
||||||
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
||||||
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
const CylinderModule: React.FC = () => {
|
const CylinderModule: React.FC = () => {
|
||||||
const { vk, cpi: globalCpi } = useWindStore();
|
const { vk, cpi: globalCpi } = useWindStore();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { PressureLegend } from '@/components/PressureLegend';
|
|||||||
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
||||||
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
||||||
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
const DomeModule: React.FC = () => {
|
const DomeModule: React.FC = () => {
|
||||||
const { vk, cpi } = useWindStore();
|
const { vk, cpi } = useWindStore();
|
||||||
|
|||||||
@@ -31,10 +31,11 @@ import { EducationalManual } from '@/components/EducationalManual';
|
|||||||
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
||||||
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
||||||
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
const DynamicsModule: React.FC = () => {
|
const DynamicsModule: React.FC = () => {
|
||||||
const { v0, s1, s3, terrainCategory, structureClass, q } = useWindStore();
|
const { v0, s1, s3, terrainCategory, structureClass, q } = useWindStore();
|
||||||
const [activeTab, setActiveTab] = useState('edificio');
|
const [activeTab, setActiveTab] = usePersistentState('DynamicsModule_activeTab', 'edificio');
|
||||||
|
|
||||||
const [structureType, setStructureType] = React.useState<StructureDynamicType>('concrete-shearwall');
|
const [structureType, setStructureType] = React.useState<StructureDynamicType>('concrete-shearwall');
|
||||||
const [height, setHeight] = React.useState(40);
|
const [height, setHeight] = React.useState(40);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import { PressureLegend } from '@/components/PressureLegend';
|
|||||||
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
||||||
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
||||||
import { useHydrationStore } from '@/store/hydrationStore';
|
import { useHydrationStore } from '@/store/hydrationStore';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
const GalpaoModule: React.FC = () => {
|
const GalpaoModule: React.FC = () => {
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Link } from 'react-router-dom';
|
|||||||
import { Warehouse, Cylinder, Church, CircleDot, Square, Layers, BarChart3, Frame, Tent, Calculator } from 'lucide-react';
|
import { Warehouse, Cylinder, Church, CircleDot, Square, Layers, BarChart3, Frame, Tent, Calculator } from 'lucide-react';
|
||||||
import { useI18n } from '../store/i18nStore';
|
import { useI18n } from '../store/i18nStore';
|
||||||
import { useWindStore } from '../store/appStore';
|
import { useWindStore } from '../store/appStore';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
// Mocked icons for bridge and tower to match App.tsx
|
// Mocked icons for bridge and tower to match App.tsx
|
||||||
const BridgeIcon = (props: React.SVGProps<SVGSVGElement>) => (
|
const BridgeIcon = (props: React.SVGProps<SVGSVGElement>) => (
|
||||||
|
|||||||
@@ -15,15 +15,16 @@ import { PressureLegend } from '@/components/PressureLegend';
|
|||||||
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
||||||
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
||||||
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
const IsolatedRoofModule: React.FC = () => {
|
const IsolatedRoofModule: React.FC = () => {
|
||||||
const { q } = useWindStore();
|
const { q } = useWindStore();
|
||||||
const [type, setType] = React.useState<'shed' | 'gable' | 'butterfly'>('shed');
|
const [type, setType] = React.useState<'shed' | 'gable' | 'butterfly'>('shed');
|
||||||
const [theta, setTheta] = React.useState(15);
|
const [theta, setTheta] = React.useState(15);
|
||||||
const [height, setHeight] = React.useState(2);
|
const [height, setHeight] = React.useState(2);
|
||||||
const [width, setWidth] = useState(10);
|
const [width, setWidth] = usePersistentState('IsolatedRoofModule_width', 10);
|
||||||
const [depth, setDepth] = useState(10);
|
const [depth, setDepth] = usePersistentState('IsolatedRoofModule_depth', 10);
|
||||||
const [viewMode, setViewMode] = useState<'solid' | 'airflow'>('solid');
|
const [viewMode, setViewMode] = usePersistentState<'solid' | 'airflow'>('IsolatedRoofModule_viewMode', 'solid');
|
||||||
|
|
||||||
const result = useMemo(() => {
|
const result = useMemo(() => {
|
||||||
if (type === 'shed') {
|
if (type === 'shed') {
|
||||||
|
|||||||
@@ -18,17 +18,18 @@ import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generi
|
|||||||
import { Plus, Trash2, Info, AlertTriangle } from 'lucide-react';
|
import { Plus, Trash2, Info, AlertTriangle } from 'lucide-react';
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from '@/components/ui/tooltip';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
const PiperackModule: React.FC = () => {
|
const PiperackModule: React.FC = () => {
|
||||||
const { q } = useWindStore();
|
const { q } = useWindStore();
|
||||||
const [width, setWidth] = useState(17);
|
const [width, setWidth] = usePersistentState('PiperackModule_width', 17);
|
||||||
const [height, setHeight] = useState(2);
|
const [height, setHeight] = usePersistentState('PiperackModule_height', 2);
|
||||||
const [elevation, setElevation] = useState(6);
|
const [elevation, setElevation] = usePersistentState('PiperackModule_elevation', 6);
|
||||||
const [spacing, setSpacing] = useState(2);
|
const [spacing, setSpacing] = usePersistentState('PiperackModule_spacing', 2);
|
||||||
const [numFrames, setNumFrames] = useState(2);
|
const [numFrames, setNumFrames] = usePersistentState('PiperackModule_numFrames', 2);
|
||||||
const [phiStruct, setPhiStruct] = useState(0.5);
|
const [phiStruct, setPhiStruct] = usePersistentState('PiperackModule_phiStruct', 0.5);
|
||||||
const [f1, setF1] = useState(1.5); // Frequência natural (Hz)
|
const [f1, setF1] = usePersistentState('PiperackModule_f1', 1.5); // Frequência natural (Hz)
|
||||||
const [pipes, setPipes] = useState<PipeDef[]>([]);
|
const [pipes, setPipes] = usePersistentState<PipeDef[]>('PiperackModule_pipes', []);
|
||||||
|
|
||||||
const pendingLoad = useHydrationStore((s) => s.pendingLoad);
|
const pendingLoad = useHydrationStore((s) => s.pendingLoad);
|
||||||
const clearPendingLoad = useHydrationStore((s) => s.clearPendingLoad);
|
const clearPendingLoad = useHydrationStore((s) => s.clearPendingLoad);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const SettingsModule: React.FC = () => {
|
|||||||
|
|
||||||
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
||||||
const logoInputRef = useRef<HTMLInputElement | null>(null);
|
const logoInputRef = useRef<HTMLInputElement | null>(null);
|
||||||
const [importing, setImporting] = useState(false);
|
const [importing, setImporting] = usePersistentState('SettingsModule_importing', false);
|
||||||
const { companyLogo, setCompanyLogo } = useWindStore();
|
const { companyLogo, setCompanyLogo } = useWindStore();
|
||||||
|
|
||||||
const exportSnapshot = () => {
|
const exportSnapshot = () => {
|
||||||
@@ -93,6 +93,7 @@ const SettingsModule: React.FC = () => {
|
|||||||
await save(newProject as any);
|
await save(newProject as any);
|
||||||
} else {
|
} else {
|
||||||
// Old snapshot import fallback
|
// Old snapshot import fallback
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
importProjectFromText(text);
|
importProjectFromText(text);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
|||||||
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
||||||
import { Eye, Box, Layers, ArrowUpRight, CheckCircle2, Wind, AlertTriangle } from 'lucide-react';
|
import { Eye, Box, Layers, ArrowUpRight, CheckCircle2, Wind, AlertTriangle } from 'lucide-react';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
const conditionLabels: Record<ShelterCondition, string> = {
|
const conditionLabels: Record<ShelterCondition, string> = {
|
||||||
cond1: '1. Estanque 3 lados (Fundo + Lados)',
|
cond1: '1. Estanque 3 lados (Fundo + Lados)',
|
||||||
@@ -32,19 +33,19 @@ const conditionLabels: Record<ShelterCondition, string> = {
|
|||||||
|
|
||||||
const ShelterModule: React.FC = () => {
|
const ShelterModule: React.FC = () => {
|
||||||
const { q } = useWindStore();
|
const { q } = useWindStore();
|
||||||
const [condition, setCondition] = useState<ShelterCondition>('cond1');
|
const [condition, setCondition] = usePersistentState<ShelterCondition>('ShelterModule_condition', 'cond1');
|
||||||
const [windAngle, setWindAngle] = useState<ShelterWindAngle>(0);
|
const [windAngle, setWindAngle] = usePersistentState<ShelterWindAngle>('ShelterModule_windAngle', 0);
|
||||||
const [depth, setDepth] = useState(6);
|
const [depth, setDepth] = usePersistentState('ShelterModule_depth', 6);
|
||||||
const [width, setWidth] = useState(10);
|
const [width, setWidth] = usePersistentState('ShelterModule_width', 10);
|
||||||
const [height, setHeight] = useState(4.8);
|
const [height, setHeight] = usePersistentState('ShelterModule_height', 4.8);
|
||||||
const [theta, setTheta] = useState(5);
|
const [theta, setTheta] = usePersistentState('ShelterModule_theta', 5);
|
||||||
const [numColumns, setNumColumns] = useState(2);
|
const [numColumns, setNumColumns] = usePersistentState('ShelterModule_numColumns', 2);
|
||||||
const [backClosure, setBackClosure] = useState(75);
|
const [backClosure, setBackClosure] = usePersistentState('ShelterModule_backClosure', 75);
|
||||||
const [backRange, setBackRange] = useState<[number, number]>([0, 75]);
|
const [backRange, setBackRange] = usePersistentState<[number, number]>('ShelterModule_backRange', [0, 75]);
|
||||||
const [leftClosure, setLeftClosure] = useState(100);
|
const [leftClosure, setLeftClosure] = usePersistentState('ShelterModule_leftClosure', 100);
|
||||||
const [rightClosure, setRightClosure] = useState(100);
|
const [rightClosure, setRightClosure] = usePersistentState('ShelterModule_rightClosure', 100);
|
||||||
const [surfaceMass, setSurfaceMass] = useState(15); // kg/m² para lona/telha leve
|
const [surfaceMass, setSurfaceMass] = usePersistentState('ShelterModule_surfaceMass', 15); // kg/m² para lona/telha leve
|
||||||
const [viewMode, setViewMode] = useState<'3d' | 'elevation' | 'airflow'>('3d');
|
const [viewMode, setViewMode] = usePersistentState<'3d' | 'elevation' | 'airflow'>('ShelterModule_viewMode', '3d');
|
||||||
|
|
||||||
const pendingLoad = useHydrationStore((s) => s.pendingLoad);
|
const pendingLoad = useHydrationStore((s) => s.pendingLoad);
|
||||||
const clearPendingLoad = useHydrationStore((s) => s.clearPendingLoad);
|
const clearPendingLoad = useHydrationStore((s) => s.clearPendingLoad);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { PressureLegend } from '@/components/PressureLegend';
|
|||||||
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
||||||
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
||||||
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
const SignModule: React.FC = () => {
|
const SignModule: React.FC = () => {
|
||||||
const { q } = useWindStore();
|
const { q } = useWindStore();
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { EducationalManual } from '@/components/EducationalManual';
|
|||||||
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
||||||
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
||||||
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
const TowerModule: React.FC = () => {
|
const TowerModule: React.FC = () => {
|
||||||
const { q } = useWindStore();
|
const { q } = useWindStore();
|
||||||
@@ -23,7 +24,7 @@ const TowerModule: React.FC = () => {
|
|||||||
const [panels, setPanels] = React.useState(5);
|
const [panels, setPanels] = React.useState(5);
|
||||||
const [phi, setPhi] = React.useState(0.2);
|
const [phi, setPhi] = React.useState(0.2);
|
||||||
const [alphaWind, setAlphaWind] = React.useState<0 | 45 | 90>(0);
|
const [alphaWind, setAlphaWind] = React.useState<0 | 45 | 90>(0);
|
||||||
const [viewMode, setViewMode] = useState<'solid' | 'airflow'>('solid');
|
const [viewMode, setViewMode] = usePersistentState<'solid' | 'airflow'>('TowerModule_viewMode', 'solid');
|
||||||
|
|
||||||
const result = useMemo(() => {
|
const result = useMemo(() => {
|
||||||
const aFace = baseWidth * height;
|
const aFace = baseWidth * height;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { PressureLegend } from '@/components/PressureLegend';
|
|||||||
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
import { WindParametersSummary } from '@/components/WindParametersSummary';
|
||||||
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
import { SaveModuleDialog } from '@/components/SaveModuleDialog';
|
||||||
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
import { exportGenericToPDF, type GenericPDFSection } from '../lib/export-generic-pdf';
|
||||||
|
import { usePersistentState } from '@/hooks/usePersistentState';
|
||||||
|
|
||||||
const VaultModule: React.FC = () => {
|
const VaultModule: React.FC = () => {
|
||||||
const { vk } = useWindStore();
|
const { vk } = useWindStore();
|
||||||
|
|||||||
Reference in New Issue
Block a user