diff --git a/dental-server/dental-client/public/version.txt b/dental-server/dental-client/public/version.txt index 8a1af3b..96d270e 100644 --- a/dental-server/dental-client/public/version.txt +++ b/dental-server/dental-client/public/version.txt @@ -1 +1 @@ -2.1.29 +2.1.46 diff --git a/dental-server/dental-client/src/components/CollapsibleSection.jsx b/dental-server/dental-client/src/components/CollapsibleSection.jsx new file mode 100644 index 0000000..8004966 --- /dev/null +++ b/dental-server/dental-client/src/components/CollapsibleSection.jsx @@ -0,0 +1,40 @@ +import { useState } from 'react'; + +/** + * Seção colapsável com chevron-down. + * Quando fechada, o conteúdo NÃO é renderizado → zero espaço em tela. + * + * Props: + * - title: string — título da seção + * - defaultOpen: boolean (default false) + * - children: ReactNode + * - className: string (opcional) — classe extra no container + * - compact: boolean (default false) — estilo menor para uso inline + */ +export default function CollapsibleSection({ + title, + defaultOpen = false, + children, + className = '', + compact = false, +}) { + const [open, setOpen] = useState(defaultOpen); + + return ( +
+ + {open &&
{children}
} +
+ ); +} diff --git a/dental-server/dental-client/src/components/TransformModal.jsx b/dental-server/dental-client/src/components/TransformModal.jsx index e4787b6..a5924c6 100644 --- a/dental-server/dental-client/src/components/TransformModal.jsx +++ b/dental-server/dental-client/src/components/TransformModal.jsx @@ -1,8 +1,23 @@ import { useState, useEffect } from 'react'; import Modal from './Modal'; +import CollapsibleSection from './CollapsibleSection'; import api from '../api/client'; import { useToast } from '../contexts/ToastContext'; +/** Detecta viewport mobile (<= 1023px) */ +function useIsMobile() { + const [mobile, setMobile] = useState(() => + typeof window !== 'undefined' ? window.innerWidth <= 1023 : false + ); + useEffect(() => { + const mql = window.matchMedia('(max-width: 1023px)'); + const handler = (e) => setMobile(e.matches); + mql.addEventListener('change', handler); + return () => mql.removeEventListener('change', handler); + }, []); + return mobile; +} + function formatDate(dateString) { if (!dateString) return '—'; return new Date(dateString).toLocaleString('pt-BR', { @@ -13,6 +28,7 @@ function formatDate(dateString) { export default function TransformModal({ isOpen, onClose, image, onSaved }) { const { showToast } = useToast(); + const isMobile = useIsMobile(); const [activeView, setActiveView] = useState('transform'); // 'transform' | 'gto' const [step, setStep] = useState('choose'); // 'choose' (4 posições) | 'finetune' const [choosePage, setChoosePage] = useState(0); // 0=rotações, 1=flip H, 2=flip V @@ -338,13 +354,15 @@ export default function TransformModal({ isOpen, onClose, image, onSaved }) { {activeView === 'transform' && step === 'finetune' && (
- {/* Original */} -
-

Original

-
- Original + {/* Original — escondido no mobile, mostrado via CollapsibeSection */} + {!isMobile && ( +
+

Original

+
+ Original +
-
+ )} {/* Preview (orientação escolhida + ajuste fino) */}
@@ -362,8 +380,10 @@ export default function TransformModal({ isOpen, onClose, image, onSaved }) { {/* Controles de rotação */}
-

Ajuste

-
+ {!isMobile && ( +

Ajuste

+ )} +
{[ { label: '-5°', delta: -5, icon: '↺' }, { label: '-1°', delta: -1, icon: '↺' }, @@ -374,7 +394,7 @@ export default function TransformModal({ isOpen, onClose, image, onSaved }) { ))} -
+
{fineTuneAngle > 0 ? '+' : ''}{fineTuneAngle}°
@@ -389,7 +409,7 @@ export default function TransformModal({ isOpen, onClose, image, onSaved }) { ))} {fineTuneAngle !== 0 && ( - )} @@ -397,40 +417,92 @@ export default function TransformModal({ isOpen, onClose, image, onSaved }) {
+ {/* Original colapsável — apenas no mobile */} + {isMobile && ( + +
+ Original +
+
+ )} + {/* Área de ação */} -
-
- -