Hide advanced signing options by default
This commit is contained in:
+5
-1
@@ -2,10 +2,14 @@
|
||||
|
||||
## Versión actual
|
||||
|
||||
- Versión base: `1.2.12`
|
||||
- Versión base: `1.2.13`
|
||||
|
||||
## Historial
|
||||
|
||||
### 1.2.13 - 2026-04-27
|
||||
|
||||
- Web y Android ocultan por defecto los detalles avanzados de `Firmar ahora` y los muestran solo bajo demanda con botón de ojo.
|
||||
|
||||
### 1.2.12 - 2026-04-23
|
||||
|
||||
- Web reordena el menú principal para mostrar `Firmar ahora` en segunda posición y `Mis documentos` justo debajo.
|
||||
|
||||
@@ -18,8 +18,8 @@ android {
|
||||
applicationId "net.linkedcorp.linkedsign"
|
||||
minSdk 26
|
||||
targetSdk 35
|
||||
versionCode 10212
|
||||
versionName "1.2.12"
|
||||
versionCode 10213
|
||||
versionName "1.2.13"
|
||||
|
||||
buildConfigField "String", "API_BASE_URL", "\"${apiBaseUrl}\""
|
||||
}
|
||||
|
||||
@@ -1330,6 +1330,7 @@ private fun SignScreen(
|
||||
var certPassword by rememberSaveable { mutableStateOf("") }
|
||||
var reason by rememberSaveable { mutableStateOf("Firmado digitalmente") }
|
||||
var location by rememberSaveable { mutableStateOf("") }
|
||||
var showAdvancedOptions by remember { mutableStateOf(false) }
|
||||
var currentPageIndex by rememberSaveable(selectedDocumentId) { mutableStateOf(0) }
|
||||
var preview by remember(selectedDocumentId) { mutableStateOf<PdfPreviewState?>(null) }
|
||||
var placement by remember(selectedDocumentId) { mutableStateOf<SignaturePlacement?>(null) }
|
||||
@@ -1339,6 +1340,9 @@ private fun SignScreen(
|
||||
val selectedDocument = state.documents.firstOrNull { it.id.toString() == selectedDocumentId }
|
||||
val signerLabel = state.userName ?: state.userEmail ?: "Firmante"
|
||||
val signatureStyle = state.signaturePreferences?.signatureStyle ?: "qr"
|
||||
val qrPosition = state.signaturePreferences?.qrPosition ?: "left"
|
||||
val qrBackground = state.signaturePreferences?.qrBackground ?: "transparent"
|
||||
val qrBorder = state.signaturePreferences?.qrBorder ?: "none"
|
||||
|
||||
LaunchedEffect(initialDocumentId, state.documents) {
|
||||
val documentId = initialDocumentId ?: return@LaunchedEffect
|
||||
@@ -1360,7 +1364,6 @@ private fun SignScreen(
|
||||
) {
|
||||
item {
|
||||
SectionCard(title = "Vista previa y firma") {
|
||||
Text("Esta versión usa la configuración visual de firma ya guardada en tu cuenta.", color = TextMuted, fontSize = AppFontSizes.sm)
|
||||
DropdownSelector(
|
||||
label = "Documento",
|
||||
options = state.documents.associate { it.id.toString() to (it.title ?: it.filename ?: "Documento ${it.id}") },
|
||||
@@ -1374,8 +1377,37 @@ private fun SignScreen(
|
||||
onSelect = { selectedCertificateId = it }
|
||||
)
|
||||
AppTextField(value = certPassword, onValueChange = { certPassword = it }, label = "Contraseña del certificado", isPassword = true)
|
||||
AppTextField(value = reason, onValueChange = { reason = it }, label = "Razón")
|
||||
AppTextField(value = location, onValueChange = { location = it }, label = "Ubicación")
|
||||
OutlinedActionButton(
|
||||
label = if (showAdvancedOptions) "Ocultar detalles" else "Mostrar detalles",
|
||||
icon = if (showAdvancedOptions) Icons.Outlined.VisibilityOff else Icons.Outlined.Visibility
|
||||
) {
|
||||
showAdvancedOptions = !showAdvancedOptions
|
||||
}
|
||||
if (showAdvancedOptions) {
|
||||
Text("Esta versión usa la configuración visual de firma ya guardada en tu cuenta.", color = TextMuted, fontSize = AppFontSizes.sm)
|
||||
AppTextField(value = reason, onValueChange = { reason = it }, label = "Razón")
|
||||
AppTextField(value = location, onValueChange = { location = it }, label = "Ubicación")
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(18.dp),
|
||||
color = SurfaceSoft,
|
||||
border = BorderStroke(1.dp, StrokeSoft)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp)
|
||||
) {
|
||||
Text("Estilo aplicado", color = BrandDark, fontSize = AppFontSizes.base, fontWeight = FontWeight.SemiBold)
|
||||
Text("La firma usará tu configuración guardada en el menú Estilo Firma.", color = TextMuted, fontSize = AppFontSizes.sm)
|
||||
Text("Tipo: $signatureStyle", color = BrandDark, fontSize = AppFontSizes.sm)
|
||||
if (signatureStyle == "qr") {
|
||||
Text("Posición QR: ${if (qrPosition == "left") "Izquierda" else "Derecha"}", color = BrandDark, fontSize = AppFontSizes.sm)
|
||||
Text("Fondo: ${if (qrBackground == "transparent") "Transparente" else "Suave"}", color = BrandDark, fontSize = AppFontSizes.sm)
|
||||
Text("Borde: ${if (qrBorder == "none") "Sin borde" else "Con borde"}", color = BrandDark, fontSize = AppFontSizes.sm)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
OutlinedActionButton("Cargar PDF para ubicar firma", Icons.Outlined.Description) {
|
||||
val documentId = selectedDocumentId.toIntOrNull() ?: return@OutlinedActionButton
|
||||
scope.launch {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "linkedsign-backend",
|
||||
"version": "1.2.12",
|
||||
"version": "1.2.13",
|
||||
"private": true,
|
||||
"description": "Initial backend for LinkedSign",
|
||||
"main": "src/server.js",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "frontend",
|
||||
"private": true,
|
||||
"version": "1.2.12",
|
||||
"version": "1.2.13",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1059,6 +1059,13 @@ select {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-inline-toggle {
|
||||
width: fit-content;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.sign-form-card form { display: flex; flex-direction: column; gap: 14px; }
|
||||
|
||||
.sign-info-panel { display: flex; flex-direction: column; gap: 14px; }
|
||||
@@ -2314,6 +2321,11 @@ select {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.btn-inline-toggle {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.steps-bar {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useSearchParams } from 'react-router-dom';
|
||||
import { listDocuments, downloadDocument, uploadDocument } from '../../api/documents';
|
||||
import { listCertificates } from '../../api/certificates';
|
||||
import { signDocument, getSignatures, downloadSigned } from '../../api/signatures';
|
||||
import { PenTool, FileText, Shield, CheckCircle, MapPin, Download, Check, Plus } from 'lucide-react';
|
||||
import { PenTool, FileText, Shield, CheckCircle, MapPin, Download, Check, Plus, Eye, EyeOff } from 'lucide-react';
|
||||
import toast from 'react-hot-toast';
|
||||
import PasswordModal from '../../components/ui/PasswordModal';
|
||||
import PdfSignaturePlacer from '../../components/ui/PdfSignaturePlacer';
|
||||
@@ -40,6 +40,7 @@ export default function SignaturesPage() {
|
||||
const [pendingSign, setPendingSign] = useState(null);
|
||||
const [uploadingDocument, setUploadingDocument] = useState(false);
|
||||
const [pendingLocalDocument, setPendingLocalDocument] = useState(null);
|
||||
const [showAdvancedOptions, setShowAdvancedOptions] = useState(false);
|
||||
const documentInputRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -293,22 +294,34 @@ export default function SignaturesPage() {
|
||||
</select>
|
||||
{certs.length === 0 && <small className="field-hint">No tienes certificados activos.</small>}
|
||||
</div>
|
||||
<div className="field">
|
||||
<label>Razón de firma</label>
|
||||
<input type="text" name="reason" value={form.reason} onChange={handleChange} />
|
||||
</div>
|
||||
<div className="field">
|
||||
<label>Ubicación</label>
|
||||
<input type="text" name="location" value={form.location} onChange={handleChange} placeholder="Ciudad, País..." />
|
||||
</div>
|
||||
<div className="info-box">
|
||||
<h4>Estilo aplicado</h4>
|
||||
<p>La firma usará tu configuración guardada en el menú <strong>Estilo Firma</strong>.</p>
|
||||
<p><strong>Tipo:</strong> {form.signatureStyle}</p>
|
||||
{form.signatureStyle === 'qr' && <p><strong>Posición QR:</strong> {form.qrPosition === 'left' ? 'Izquierda' : 'Derecha'}</p>}
|
||||
{form.signatureStyle === 'qr' && <p><strong>Fondo:</strong> {form.qrBackground === 'transparent' ? 'Transparente' : 'Suave'}</p>}
|
||||
{form.signatureStyle === 'qr' && <p><strong>Borde:</strong> {form.qrBorder === 'none' ? 'Sin borde' : 'Con borde'}</p>}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-ghost btn-inline-toggle"
|
||||
onClick={() => setShowAdvancedOptions((current) => !current)}
|
||||
>
|
||||
{showAdvancedOptions ? <EyeOff size={16} /> : <Eye size={16} />}
|
||||
{showAdvancedOptions ? 'Ocultar detalles' : 'Mostrar detalles'}
|
||||
</button>
|
||||
{showAdvancedOptions && (
|
||||
<>
|
||||
<div className="field">
|
||||
<label>Razón de firma</label>
|
||||
<input type="text" name="reason" value={form.reason} onChange={handleChange} />
|
||||
</div>
|
||||
<div className="field">
|
||||
<label>Ubicación</label>
|
||||
<input type="text" name="location" value={form.location} onChange={handleChange} placeholder="Ciudad, País..." />
|
||||
</div>
|
||||
<div className="info-box">
|
||||
<h4>Estilo aplicado</h4>
|
||||
<p>La firma usará tu configuración guardada en el menú <strong>Estilo Firma</strong>.</p>
|
||||
<p><strong>Tipo:</strong> {form.signatureStyle}</p>
|
||||
{form.signatureStyle === 'qr' && <p><strong>Posición QR:</strong> {form.qrPosition === 'left' ? 'Izquierda' : 'Derecha'}</p>}
|
||||
{form.signatureStyle === 'qr' && <p><strong>Fondo:</strong> {form.qrBackground === 'transparent' ? 'Transparente' : 'Suave'}</p>}
|
||||
{form.signatureStyle === 'qr' && <p><strong>Borde:</strong> {form.qrBorder === 'none' ? 'Sin borde' : 'Con borde'}</p>}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<button className="btn btn-primary btn-full" onClick={handleGoToPlace}>
|
||||
<MapPin size={16} /> Elegir posición de firma →
|
||||
</button>
|
||||
@@ -372,7 +385,7 @@ export default function SignaturesPage() {
|
||||
<div className="step-nav">
|
||||
<button className="btn btn-ghost" onClick={() => setStep(0)}>← Volver</button>
|
||||
<p className="step-desc">
|
||||
Haz clic donde quieres que aparezca la firma en <strong>{selectedDoc?.title}</strong>
|
||||
Haz clic donde quieres que aparezca la firma en <strong>{selectedDocumentTitle}</strong>
|
||||
</p>
|
||||
</div>
|
||||
<PdfSignaturePlacer
|
||||
@@ -396,15 +409,27 @@ export default function SignaturesPage() {
|
||||
<h3>Posición confirmada — listo para firmar</h3>
|
||||
</div>
|
||||
<div className="sign-confirm-details">
|
||||
<p><strong>Documento:</strong> {selectedDoc?.title}</p>
|
||||
<p><strong>Documento:</strong> {selectedDocumentTitle}</p>
|
||||
<p><strong>Certificado:</strong> {selectedCert?.alias}</p>
|
||||
<p><strong>Razón:</strong> {form.reason}</p>
|
||||
{form.location && <p><strong>Ubicación:</strong> {form.location}</p>}
|
||||
<p><strong>Estilo visual:</strong> {form.signatureStyle}</p>
|
||||
{form.signatureStyle === 'qr' && <p><strong>Posición QR:</strong> {form.qrPosition === 'left' ? 'Izquierda' : 'Derecha'}</p>}
|
||||
{form.signatureStyle === 'qr' && <p><strong>Fondo:</strong> {form.qrBackground === 'transparent' ? 'Transparente' : 'Suave'}</p>}
|
||||
{form.signatureStyle === 'qr' && <p><strong>Borde:</strong> {form.qrBorder === 'none' ? 'Sin borde' : 'Con borde'}</p>}
|
||||
<p><strong>Página:</strong> {(sigPlacement?.page ?? 0) + 1}</p>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-ghost btn-inline-toggle"
|
||||
onClick={() => setShowAdvancedOptions((current) => !current)}
|
||||
>
|
||||
{showAdvancedOptions ? <EyeOff size={16} /> : <Eye size={16} />}
|
||||
{showAdvancedOptions ? 'Ocultar detalles' : 'Mostrar detalles'}
|
||||
</button>
|
||||
{showAdvancedOptions && (
|
||||
<>
|
||||
<p><strong>Razón:</strong> {form.reason}</p>
|
||||
{form.location && <p><strong>Ubicación:</strong> {form.location}</p>}
|
||||
<p><strong>Estilo visual:</strong> {form.signatureStyle}</p>
|
||||
{form.signatureStyle === 'qr' && <p><strong>Posición QR:</strong> {form.qrPosition === 'left' ? 'Izquierda' : 'Derecha'}</p>}
|
||||
{form.signatureStyle === 'qr' && <p><strong>Fondo:</strong> {form.qrBackground === 'transparent' ? 'Transparente' : 'Suave'}</p>}
|
||||
{form.signatureStyle === 'qr' && <p><strong>Borde:</strong> {form.qrBorder === 'none' ? 'Sin borde' : 'Con borde'}</p>}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="sign-confirm-actions">
|
||||
<button className="btn btn-ghost" onClick={() => setStep(1)}>← Cambiar posición</button>
|
||||
|
||||
Reference in New Issue
Block a user