463 lines
27 KiB
HTML
463 lines
27 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="pt-BR">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||
<title>Gerenciador de Imagens Dentais</title>
|
||
<meta name="description" content="Sistema de gerenciamento de imagens de raio-X dental">
|
||
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
||
<link rel="stylesheet" href="/style.css?v=2.4">
|
||
</head>
|
||
<body>
|
||
<div class="app-container">
|
||
<!-- Sidebar -->
|
||
<aside class="sidebar">
|
||
<div class="sidebar-header">
|
||
<h2>🦷 DentalSys</h2>
|
||
</div>
|
||
<nav class="sidebar-nav">
|
||
<a href="/" class="nav-item active">
|
||
<span class="icon">🖼️</span> Pacientes
|
||
</a>
|
||
<a href="#" class="nav-item" onclick="openCreatePatientModal(); return false;">
|
||
<span class="icon">➕</span> Novo Paciente
|
||
</a>
|
||
<a href="/clients" class="nav-item">
|
||
<span class="icon">🖥️</span> Dispositivos
|
||
</a>
|
||
<a href="#" class="nav-item" onclick="openSettingsModal(); return false;">
|
||
<span class="icon">⚙️</span> Configurações
|
||
</a>
|
||
<a href="#" class="nav-item" onclick="openPluginsModal(); return false;">
|
||
<span class="icon">🔌</span> Plugins / Wasabi
|
||
</a>
|
||
<a href="#" class="nav-item" onclick="openSyncModal(); return false;">
|
||
<span class="icon">🔄</span> Sincronização
|
||
</a>
|
||
<a href="/reset" class="nav-item" style="color: #dc3545;">
|
||
<span class="icon">⚠️</span> Zerar Sistema
|
||
</a>
|
||
<div class="nav-divider"></div>
|
||
<button id="toggleDisabledBtn" class="btn btn-secondary" style="margin: 10px 20px; width: calc(100% - 40px);">
|
||
<span id="toggleText">Ocultas</span>
|
||
</button>
|
||
</nav>
|
||
</aside>
|
||
|
||
<!-- Main Content -->
|
||
<main class="main-content">
|
||
<!-- Header -->
|
||
<header class="header">
|
||
<div class="header-content">
|
||
<div class="header-left">
|
||
<button id="backBtn" class="btn btn-back" style="display:none;">
|
||
← Voltar
|
||
</button>
|
||
<h1 id="mainTitle">Galeria de Imagens</h1>
|
||
</div>
|
||
<div class="header-actions">
|
||
<select id="clientFilter" class="client-filter">
|
||
<option value="">📋 Todos os Clientes</option>
|
||
</select>
|
||
<input
|
||
type="search"
|
||
id="searchInput"
|
||
class="search-input"
|
||
placeholder="🔍 Pesquisar paciente..."
|
||
>
|
||
<button class="btn btn-secondary" onclick="loadClientsList()">
|
||
<span class="icon">🔄</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Patient sub-header (shown in patient-images view) -->
|
||
<div id="patientHeader" class="patient-header" style="display:none;">
|
||
<div class="patient-header-info">
|
||
<div id="patientTitle" class="patient-header-name"></div>
|
||
<div id="patientMeta" class="patient-header-meta"></div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Scrollable content area -->
|
||
<div class="content-scroll">
|
||
|
||
<!-- Loading State -->
|
||
<div id="loadingState" class="loading">
|
||
<div class="spinner"></div>
|
||
<p>Carregando...</p>
|
||
</div>
|
||
|
||
<!-- Empty State -->
|
||
<div id="emptyState" class="empty-state" style="display: none;">
|
||
<div class="empty-icon">📭</div>
|
||
<h2>Nenhum resultado encontrado</h2>
|
||
<p>As imagens aparecerão aqui quando forem enviadas pelo cliente Windows</p>
|
||
</div>
|
||
|
||
<!-- Images / Patients Grid -->
|
||
<div id="imagesGrid" class="images-grid"> </div>
|
||
|
||
</div><!-- end .content-scroll -->
|
||
</main>
|
||
</div>
|
||
|
||
<!-- Transform Modal -->
|
||
<div id="transformModal" class="modal">
|
||
<div class="modal-content modal-large">
|
||
<div class="modal-header" style="display: flex; justify-content: space-between; width: 100%; align-items: center; border-bottom: 1px solid #eee; padding-bottom: 15px;">
|
||
<div style="display: flex; align-items: center; gap: 15px; flex-wrap: wrap;">
|
||
<h2 id="transformModalTitle" style="margin: 0; font-size: 1.4rem;"><!-- Dynamic Title (Patient + Date) --></h2>
|
||
<div style="display: flex; gap: 8px;">
|
||
<button id="btnShowTransform" class="btn btn-primary" onclick="toggleModalView('transform')" style="width: 60px; height: 40px; padding: 0; display: flex; align-items: center; justify-content: center; font-size: 1.2rem;" title="Ajustar Imagem">🔄</button>
|
||
<button id="btnShowGto" class="btn btn-secondary" onclick="toggleModalView('gto')" style="width: 60px; height: 40px; padding: 0; display: flex; align-items: center; justify-content: center; font-size: 1.2rem;" title="Gerenciar GTOs">📋</button>
|
||
<button id="btnShowInfo" class="btn btn-secondary" onclick="toggleModalInfo()" style="width: 60px; height: 40px; padding: 0; display: flex; align-items: center; justify-content: center; font-size: 1.2rem;" title="Informações">ℹ️</button>
|
||
<button id="btnResetImage" class="btn btn-danger" onclick="resetImageToOriginal()" style="width: 60px; height: 40px; padding: 0; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; background-color: #ff6b6b; border-color: #ff6b6b; color: white;" title="Resetar para Original">↩️</button>
|
||
</div>
|
||
</div>
|
||
<span class="modal-close" id="closeTransformModal">×</span>
|
||
</div>
|
||
|
||
<div class="modal-body" style="padding-top: 15px;">
|
||
<!-- Bloco oculto de informações -->
|
||
<div id="transformExtraInfo" style="display: none; font-size: 0.95rem; color: #555; background: #f8f9fa; padding: 12px 20px; border-radius: 8px; border: 1px solid #eee; margin-bottom: 15px;">
|
||
<!-- Preenchido via JS -->
|
||
</div>
|
||
|
||
<!-- View 1: Transforms -->
|
||
<div id="transformViewWrapper" style="display: flex; flex-direction: column; flex: 1; min-height: 0; height: 100%;">
|
||
<div id="transformOptions" class="transform-grid" style="flex: 1; min-height: 0;"></div>
|
||
<div id="transformActionArea" style="display: none; margin-top: 15px; background: #f8f9fa; padding: 15px; border-radius: 8px; flex-shrink: 0; border: 1px solid #e3e8ee;">
|
||
<textarea id="newImageRemark" class="search-input" rows="2" style="width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 6px;" placeholder="Nova observação (opcional)"></textarea>
|
||
<div style="display: flex; gap: 10px; margin-top: 10px;">
|
||
<button class="btn btn-secondary" style="flex: 1; padding: 12px; font-size: 1.1rem;" onclick="clearTransformSelection()">Cancelar</button>
|
||
<button id="btnSaveTransform" class="btn btn-primary" style="flex: 2; padding: 12px; font-size: 1.1rem;" onclick="saveSelectedTransform()">Salvar Nova Imagem</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Bloco de Ajuste Fino (Integrado na legenda do card selecionado) -->
|
||
<div id="fineTuneContainer" style="display: none;" onclick="event.stopPropagation()">
|
||
<div class="fine-tune-left-btns">
|
||
<button type="button" onclick="adjustFineTune(-5)" title="Rotacionar -5°">-5°</button>
|
||
<button type="button" onclick="adjustFineTune(-1)" title="Rotacionar -1°">-1°</button>
|
||
</div>
|
||
|
||
<div id="fineTuneLabelPlaceholder"></div>
|
||
|
||
<div class="fine-tune-right-btns">
|
||
<button type="button" onclick="adjustFineTune(1)" title="Rotacionar +1°">+1°</button>
|
||
<button type="button" onclick="adjustFineTune(5)" title="Rotacionar +5°">+5°</button>
|
||
</div>
|
||
|
||
<button type="button" id="btnResetFineTune" onclick="resetFineTune()" style="display: none;" title="Resetar ajuste fino">↩️ Reset</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- View 2: GTO List & Link -->
|
||
<div id="gtoView" style="display: none;">
|
||
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
|
||
<h3 style="margin-top: 0; font-size: 1.1rem; margin-bottom: 15px;">Cadastrar Nova GTO</h3>
|
||
<div style="display: flex; gap: 10px;">
|
||
<input type="text" id="inlineGtoNumber" class="search-input" placeholder="Número/ID da GTO" style="flex: 1; padding: 10px;">
|
||
<input type="text" id="inlineGtoDesc" class="search-input" placeholder="Descrição (Opcional)" style="flex: 2; padding: 10px;">
|
||
<button class="btn btn-primary" onclick="inlineCreateGto()">Cadastrar</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 15px;">
|
||
<h3 style="margin: 0; font-size: 1.1rem;">Vincular esta imagem a uma GTO:</h3>
|
||
<button class="btn btn-success" onclick="linkImageToGto()" id="btnLinkGto">✅ Vincular Selecionada</button>
|
||
</div>
|
||
|
||
<div id="gtoListContainer" style="border: 1px solid #ddd; border-radius: 8px; overflow: hidden;">
|
||
<!-- GTO list goes here -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Modal Novo Paciente -->
|
||
<div class="modal" id="create-patient-modal">
|
||
<div class="modal-content" style="max-width: 500px; height: auto; border-radius: var(--radius);">
|
||
<div class="modal-header">
|
||
<h2>Novo Paciente</h2>
|
||
<div class="modal-close" onclick="closeCreatePatientModal()">×</div>
|
||
</div>
|
||
<div class="modal-body" style="overflow-y: auto;">
|
||
<form id="create-patient-form" onsubmit="submitCreatePatient(event)">
|
||
<div class="form-group">
|
||
<label>Nome *</label>
|
||
<input type="text" id="patient-first-name" required placeholder="Ex: João">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Sobrenome *</label>
|
||
<input type="text" id="patient-last-name" required placeholder="Ex: Silva">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Dentista</label>
|
||
<input type="text" id="patient-doctor" placeholder="Nome do dentista responsável">
|
||
</div>
|
||
<div style="display: flex; gap: 12px;">
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Data de Nascimento</label>
|
||
<input type="date" id="patient-birthday">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label>Gênero</label>
|
||
<select id="patient-gender">
|
||
<option value="0">Masculino</option>
|
||
<option value="1">Feminino</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Telefone</label>
|
||
<input type="text" id="patient-phone" placeholder="(11) 99999-9999">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Observações</label>
|
||
<textarea id="patient-remark" rows="3" placeholder="Informações adicionais..."></textarea>
|
||
</div>
|
||
<button type="submit" class="btn btn-primary" style="width: 100%; margin-top: 10px;">
|
||
Salvar Paciente
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Modal Nova GTO -->
|
||
<div class="modal" id="create-gto-modal">
|
||
<div class="modal-content" style="max-width: 400px; height: auto; border-radius: var(--radius);">
|
||
<div class="modal-header">
|
||
<h2>Nova GTO</h2>
|
||
<div class="modal-close" onclick="closeCreateGtoModal()">×</div>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form id="create-gto-form" onsubmit="submitCreateGto(event)">
|
||
<div class="form-group">
|
||
<label>Número/ID da GTO *</label>
|
||
<input type="text" id="gto-number" required placeholder="Ex: GTO-2023-001">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Descrição (opcional)</label>
|
||
<textarea id="gto-description" rows="3" placeholder="Informações da guia..."></textarea>
|
||
</div>
|
||
<button type="submit" class="btn btn-primary" style="width: 100%; margin-top: 10px;">
|
||
Criar GTO
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Toast de Notificação -->
|
||
<div class="toast" id="toast">Operação realizada com sucesso!</div>
|
||
|
||
<!-- Settings Modal -->
|
||
<div id="settingsModal" class="modal">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2>⚙️ Configurações da Conta</h2>
|
||
<span class="close-modal" onclick="closeSettingsModal()">×</span>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form id="settingsForm" onsubmit="updateCredentials(event)">
|
||
<div class="form-group">
|
||
<label for="currentPassword">Senha Atual (Obrigatório)*</label>
|
||
<input type="password" id="currentPassword" class="form-control" placeholder="Digite sua senha atual para autorizar" required>
|
||
</div>
|
||
|
||
<hr style="margin: 20px 0; border: none; border-top: 1px solid #eee;">
|
||
<p style="margin-bottom: 15px; color: #666; font-size: 0.9rem;">Preencha apenas os campos que deseja alterar:</p>
|
||
|
||
<div class="form-group">
|
||
<label for="newUsername">Novo Nome de Usuário</label>
|
||
<input type="text" id="newUsername" class="form-control" placeholder="Deixe em branco para não alterar">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="newPassword">Nova Senha</label>
|
||
<input type="password" id="newPassword" class="form-control" placeholder="Deixe em branco para não alterar">
|
||
</div>
|
||
|
||
<div class="form-actions" style="margin-top: 25px; display: flex; justify-content: flex-end; gap: 10px;">
|
||
<button type="button" class="btn btn-secondary" onclick="closeSettingsModal()">Cancelar</button>
|
||
<button type="submit" class="btn btn-primary" id="btnSaveSettings">Salvar Alterações</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Plugins / Wasabi Modal -->
|
||
<div id="pluginsModal" class="modal">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2>🔌 Configuração do Wasabi Storage</h2>
|
||
<span class="modal-close" onclick="closePluginsModal()">×</span>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form id="pluginsForm" onsubmit="updatePluginsConfig(event)">
|
||
<div style="background: #f8f9fa; padding: 12px 18px; border-radius: 8px; border: 1px solid #eee; margin-bottom: 20px; font-size: 0.95rem; color: #555;">
|
||
Configure as credenciais e bucket do **Wasabi S3** para habilitar o armazenamento na nuvem. Se desativado, o sistema usará o armazenamento local do servidor de forma automática.
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="wasabiAccessKey">Access Key *</label>
|
||
<input type="text" id="wasabiAccessKey" placeholder="Ex: AIPL5M4G..." required>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="wasabiSecretKey">Secret Key *</label>
|
||
<input type="password" id="wasabiSecretKey" placeholder="Sua Secret Key" required>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="wasabiBucket">Bucket Ativo *</label>
|
||
<input type="text" id="wasabiBucket" placeholder="Ex: meu-bucket-rx" required>
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 12px;">
|
||
<div class="form-group" style="flex: 1;">
|
||
<label for="wasabiRegion">Região</label>
|
||
<input type="text" id="wasabiRegion" placeholder="Ex: us-east-1 (padrão)">
|
||
</div>
|
||
<div class="form-group" style="flex: 1;">
|
||
<label for="wasabiEndpoint">Endpoint</label>
|
||
<input type="text" id="wasabiEndpoint" placeholder="Ex: s3.wasabisys.com">
|
||
</div>
|
||
</div>
|
||
|
||
<div id="pluginsStatusAlert" style="display: none; padding: 10px; border-radius: 6px; font-size: 0.9rem; margin-top: 15px;"></div>
|
||
|
||
<div class="form-actions" style="margin-top: 25px; display: flex; justify-content: flex-end; gap: 10px; border-top: 1px solid #eee; padding-top: 15px;">
|
||
<button type="button" class="btn btn-secondary" onclick="closePluginsModal()">Cancelar</button>
|
||
<button type="submit" class="btn btn-primary" id="btnSavePlugins">Salvar Configurações</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Sync / Upload Modal -->
|
||
<div id="syncModal" class="modal">
|
||
<div class="modal-content" style="max-width: 650px; height: auto; border-radius: var(--radius);">
|
||
<div class="modal-header">
|
||
<h2>🔄 Área de Sincronização</h2>
|
||
<span class="modal-close" onclick="closeSyncModal()">×</span>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="sync-tabs">
|
||
<button type="button" id="tabBtnDevices" class="sync-tab-btn active" onclick="switchSyncTab('devices')">💻 Dispositivos Conectados</button>
|
||
<button type="button" id="tabBtnUpload" class="sync-tab-btn" onclick="switchSyncTab('upload')">📤 Envio Manual</button>
|
||
</div>
|
||
|
||
<!-- Tab 1: Dispositivos -->
|
||
<div id="tab-devices" class="sync-tab-content active">
|
||
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border: 1px solid #eee; margin-bottom: 20px; font-size: 0.95rem; color: #555; line-height: 1.5;">
|
||
Os computadores clientes com Windows instalados e ativos enviam imagens em tempo real. Você pode solicitar que eles façam uma sincronização manual forçada com o servidor enviando um sinal.
|
||
</div>
|
||
|
||
<div id="syncDevicesLoading" class="loading" style="padding: 20px 0;">
|
||
<div class="spinner" style="width: 30px; height: 30px; margin-bottom: 10px;"></div>
|
||
<p>Buscando dispositivos online...</p>
|
||
</div>
|
||
|
||
<div id="syncDevicesEmpty" style="display: none; text-align: center; padding: 30px 20px; color: #666;">
|
||
<span style="font-size: 2.5rem; display: block; margin-bottom: 10px;">📭</span>
|
||
<p>Nenhum dispositivo Windows conectado no momento.</p>
|
||
</div>
|
||
|
||
<div id="syncDeviceList" class="sync-device-list" style="display: none;">
|
||
<!-- Preenchido via Javascript -->
|
||
</div>
|
||
|
||
<div style="margin-top: 25px; border-top: 1px solid #eee; padding-top: 15px; display: flex; justify-content: flex-end; gap: 10px;">
|
||
<button type="button" class="btn btn-secondary" onclick="closeSyncModal()">Fechar</button>
|
||
<button type="button" class="btn btn-primary" onclick="triggerSyncFromModal()" id="btnTriggerSyncModal">
|
||
<span class="icon">🔄</span> Enviar Sinal de Sincronização
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tab 2: Envio Manual -->
|
||
<div id="tab-upload" class="sync-tab-content">
|
||
<form id="manualUploadForm" onsubmit="handleManualUploadSubmit(event)">
|
||
<div class="form-group">
|
||
<label for="uploadPatientSelect">Paciente *</label>
|
||
<div style="display: flex; gap: 10px;">
|
||
<select id="uploadPatientSelect" onchange="toggleNewPatientFields()" required style="flex: 1;">
|
||
<option value="">-- Selecione o Paciente --</option>
|
||
<option value="NEW_PATIENT">➕ Novo Paciente...</option>
|
||
</select>
|
||
<button type="button" class="btn btn-secondary" onclick="refreshUploadPatients()" title="Atualizar Lista" style="width: 44px; padding: 0; display: flex; align-items: center; justify-content: center;">
|
||
🔄
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Campos para Novo Paciente (ocultos por padrão) -->
|
||
<div id="newPatientFields" style="display: none; background: #f8f9fa; padding: 15px; border-radius: 8px; border: 1px solid #eee; margin-bottom: 18px; animation: slideDown 0.2s ease;">
|
||
<h4 style="margin: 0 0 12px 0; color: var(--dark-color); font-size: 0.95rem;">Dados do Novo Paciente</h4>
|
||
<div style="display: flex; gap: 12px; margin-bottom: 12px;">
|
||
<div style="flex: 1;">
|
||
<label style="font-size: 0.82rem; font-weight: 600; display: block; margin-bottom: 5px;">Nome *</label>
|
||
<input type="text" id="uploadNewPatientFirstName" placeholder="Ex: Maria" style="width: 100%; padding: 8px 12px; border: 1px solid #ccc; border-radius: 4px;">
|
||
</div>
|
||
<div style="flex: 1;">
|
||
<label style="font-size: 0.82rem; font-weight: 600; display: block; margin-bottom: 5px;">Sobrenome *</label>
|
||
<input type="text" id="uploadNewPatientLastName" placeholder="Ex: Oliveira" style="width: 100%; padding: 8px 12px; border: 1px solid #ccc; border-radius: 4px;">
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label style="font-size: 0.82rem; font-weight: 600; display: block; margin-bottom: 5px;">Dentista Responsável</label>
|
||
<input type="text" id="uploadNewPatientDoctor" placeholder="Nome do dentista (opcional)" style="width: 100%; padding: 8px 12px; border: 1px solid #ccc; border-radius: 4px;">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="uploadRemark">Observações / Detalhes (Opcional)</label>
|
||
<textarea id="uploadRemark" placeholder="Ex: Raio-X Panorâmico" rows="2" style="width: 100%; padding: 10px; border: 2px solid var(--border-color); border-radius: var(--radius-sm); font-family: inherit; font-size: 1rem; resize: vertical;"></textarea>
|
||
</div>
|
||
|
||
<!-- Zona de Drag and Drop -->
|
||
<div class="drag-drop-zone" id="uploadDragDropZone">
|
||
<div class="drag-drop-icon">📸</div>
|
||
<div class="drag-drop-text">Arraste as imagens aqui ou clique para selecionar</div>
|
||
<div class="drag-drop-subtext">Suporta arquivos JPG, JPEG e PNG (máx. 10MB por imagem)</div>
|
||
<input type="file" id="uploadFileInput" multiple accept="image/png, image/jpeg, image/jpg" style="display: none;">
|
||
</div>
|
||
|
||
<!-- Previews das Imagens Selecionadas -->
|
||
<div class="upload-previews" id="uploadPreviewsContainer"></div>
|
||
|
||
<!-- Progresso de Envio -->
|
||
<div class="upload-progress-container" id="uploadProgressContainer" style="display: none;">
|
||
<div class="progress-bar-label">
|
||
<span id="uploadProgressText">Enviando imagens...</span>
|
||
<span id="uploadProgressPercent">0%</span>
|
||
</div>
|
||
<div class="progress-bar-track">
|
||
<div class="progress-bar-fill" id="uploadProgressBarFill"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-actions" style="margin-top: 25px; border-top: 1px solid #eee; padding-top: 15px; display: flex; justify-content: flex-end; gap: 10px;">
|
||
<button type="button" class="btn btn-secondary" onclick="closeSyncModal()">Cancelar</button>
|
||
<button type="submit" class="btn btn-primary" id="btnSubmitManualUpload" disabled>Enviar Imagens</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Application Script -->
|
||
<script src="/socket.io/socket.io.js"></script>
|
||
<script src="/app.js?v=2.4"></script>
|
||
</body>
|
||
</html>
|