implantação da fase 2 e 3
This commit is contained in:
231
app/views/devise/sessions/new.html.erb
Normal file
231
app/views/devise/sessions/new.html.erb
Normal file
@@ -0,0 +1,231 @@
|
||||
<%# app/views/devise/sessions/new.html.erb %>
|
||||
<div class="min-h-screen bg-[#0a0a0a] flex items-center justify-center px-4">
|
||||
<div class="w-full max-w-md">
|
||||
|
||||
<%# Logo / Header %>
|
||||
<div class="text-center mb-10">
|
||||
<div class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-[#f97316] mb-4">
|
||||
<svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 16V6a1 1 0 00-1-1H4a1 1 0 00-1 1v10a1 1 0 001 1h1m8-1a1 1 0 01-1 1H9m4-1V8a1 1 0 011-1h2.586a1 1 0 01.707.293l3.414 3.414a1 1 0 01.293.707V16a1 1 0 01-1 1h-1m-6-1a1 1 0 001 1h1M5 17a2 2 0 104 0m-4 0a2 2 0 114 0m6 0a2 2 0 104 0m-4 0a2 2 0 114 0"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1 class="text-3xl font-bold text-white">Gade Logística</h1>
|
||||
<p class="text-gray-400 mt-1 text-sm">Sistema de Controle de Custos</p>
|
||||
</div>
|
||||
|
||||
<%# Flash messages %>
|
||||
<% if flash[:alert] %>
|
||||
<div class="mb-4 p-4 bg-red-900/40 border border-red-500/50 rounded-xl text-red-300 text-sm">
|
||||
<%= flash[:alert] %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%# Tabs: Email / PIN %>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl overflow-hidden border border-white/5">
|
||||
|
||||
<%# Tab switcher %>
|
||||
<div class="flex border-b border-white/10">
|
||||
<button id="tab-email"
|
||||
onclick="switchTab('email')"
|
||||
class="flex-1 py-4 text-sm font-medium transition-colors tab-active text-[#f97316] border-b-2 border-[#f97316]">
|
||||
📧 E-mail
|
||||
</button>
|
||||
<button id="tab-pin"
|
||||
onclick="switchTab('pin')"
|
||||
class="flex-1 py-4 text-sm font-medium transition-colors text-gray-400 hover:text-white border-b-2 border-transparent">
|
||||
🔑 PIN Motorista
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<%# Login por e-mail %>
|
||||
<div id="form-email" class="p-8">
|
||||
<%= form_with(url: user_session_path, method: :post) do |f| %>
|
||||
<div class="space-y-5">
|
||||
<div>
|
||||
<%= f.label :email, 'E-mail', class: 'block text-sm font-medium text-gray-300 mb-1.5' %>
|
||||
<%= f.email_field :email,
|
||||
autofocus: true,
|
||||
autocomplete: 'email',
|
||||
class: 'w-full px-4 py-3 bg-[#0a0a0a] border border-white/10 rounded-xl text-white
|
||||
placeholder-gray-600 focus:outline-none focus:border-[#f97316] focus:ring-1
|
||||
focus:ring-[#f97316] transition-colors text-base',
|
||||
placeholder: 'admin@gade.com' %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= f.label :password, 'Senha', class: 'block text-sm font-medium text-gray-300 mb-1.5' %>
|
||||
<%= f.password_field :password,
|
||||
autocomplete: 'current-password',
|
||||
class: 'w-full px-4 py-3 bg-[#0a0a0a] border border-white/10 rounded-xl text-white
|
||||
placeholder-gray-600 focus:outline-none focus:border-[#f97316] focus:ring-1
|
||||
focus:ring-[#f97316] transition-colors text-base',
|
||||
placeholder: '••••••••' %>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="flex items-center gap-2 cursor-pointer">
|
||||
<%= f.check_box :remember_me,
|
||||
class: 'w-4 h-4 rounded accent-[#f97316]' %>
|
||||
<span class="text-sm text-gray-400">Lembrar</span>
|
||||
</label>
|
||||
<%= link_to 'Esqueci a senha', new_user_password_path,
|
||||
class: 'text-sm text-[#f97316] hover:text-orange-400 transition-colors' %>
|
||||
</div>
|
||||
|
||||
<%= f.submit 'Entrar',
|
||||
class: 'w-full py-3.5 bg-[#f97316] hover:bg-orange-500 text-white font-semibold
|
||||
rounded-xl transition-colors cursor-pointer text-base min-h-[48px]' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%# Login por PIN %>
|
||||
<div id="form-pin" class="p-8 hidden">
|
||||
<%= form_with(url: user_session_path, method: :post) do |f| %>
|
||||
<%= f.hidden_field :pin_login, value: '1' %>
|
||||
|
||||
<div class="space-y-6">
|
||||
<div class="text-center">
|
||||
<p class="text-gray-400 text-sm mb-6">Digite seu PIN de 4 dígitos</p>
|
||||
|
||||
<%# PIN display visual %>
|
||||
<div class="flex justify-center gap-3 mb-6" id="pin-display">
|
||||
<% 4.times do |i| %>
|
||||
<div id="pin-dot-<%= i %>"
|
||||
class="w-14 h-14 rounded-xl bg-[#0a0a0a] border-2 border-white/10
|
||||
flex items-center justify-center text-2xl font-bold text-white
|
||||
transition-all duration-150">
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= f.hidden_field :pin, id: 'pin-value' %>
|
||||
|
||||
<%# Teclado numérico %>
|
||||
<div class="grid grid-cols-3 gap-3 max-w-[240px] mx-auto" id="pin-keypad">
|
||||
<% [1,2,3,4,5,6,7,8,9].each do |n| %>
|
||||
<button type="button"
|
||||
onclick="pinPress('<%= n %>')"
|
||||
class="h-14 rounded-xl bg-[#0a0a0a] border border-white/10 text-white
|
||||
text-xl font-semibold hover:bg-[#f97316] hover:border-[#f97316]
|
||||
active:scale-95 transition-all min-h-[48px]">
|
||||
<%= n %>
|
||||
</button>
|
||||
<% end %>
|
||||
<button type="button"
|
||||
onclick="pinClear()"
|
||||
class="h-14 rounded-xl bg-[#0a0a0a] border border-white/10 text-gray-400
|
||||
text-sm hover:bg-red-900/40 hover:border-red-500/50 hover:text-red-400
|
||||
active:scale-95 transition-all">
|
||||
✕
|
||||
</button>
|
||||
<button type="button"
|
||||
onclick="pinPress('0')"
|
||||
class="h-14 rounded-xl bg-[#0a0a0a] border border-white/10 text-white
|
||||
text-xl font-semibold hover:bg-[#f97316] hover:border-[#f97316]
|
||||
active:scale-95 transition-all">
|
||||
0
|
||||
</button>
|
||||
<button type="button"
|
||||
onclick="pinBackspace()"
|
||||
class="h-14 rounded-xl bg-[#0a0a0a] border border-white/10 text-gray-400
|
||||
text-lg hover:bg-white/5 active:scale-95 transition-all">
|
||||
⌫
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= f.submit 'Entrar com PIN',
|
||||
id: 'btn-pin-submit',
|
||||
class: 'w-full py-3.5 bg-[#f97316] hover:bg-orange-500 text-white font-semibold
|
||||
rounded-xl transition-colors cursor-pointer text-base min-h-[48px]
|
||||
disabled:opacity-40 disabled:cursor-not-allowed',
|
||||
disabled: true %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-center text-gray-600 text-xs mt-6">
|
||||
Gade Hospitalar © <%= Date.today.year %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let pinDigits = [];
|
||||
|
||||
function switchTab(tab) {
|
||||
const emailForm = document.getElementById('form-email');
|
||||
const pinForm = document.getElementById('form-pin');
|
||||
const tabEmail = document.getElementById('tab-email');
|
||||
const tabPin = document.getElementById('tab-pin');
|
||||
|
||||
if (tab === 'email') {
|
||||
emailForm.classList.remove('hidden');
|
||||
pinForm.classList.add('hidden');
|
||||
tabEmail.classList.add('text-[#f97316]', 'border-[#f97316]');
|
||||
tabEmail.classList.remove('text-gray-400', 'border-transparent');
|
||||
tabPin.classList.add('text-gray-400', 'border-transparent');
|
||||
tabPin.classList.remove('text-[#f97316]', 'border-[#f97316]');
|
||||
} else {
|
||||
pinForm.classList.remove('hidden');
|
||||
emailForm.classList.add('hidden');
|
||||
tabPin.classList.add('text-[#f97316]', 'border-[#f97316]');
|
||||
tabPin.classList.remove('text-gray-400', 'border-transparent');
|
||||
tabEmail.classList.add('text-gray-400', 'border-transparent');
|
||||
tabEmail.classList.remove('text-[#f97316]', 'border-[#f97316]');
|
||||
}
|
||||
}
|
||||
|
||||
function updatePinDisplay() {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const dot = document.getElementById(`pin-dot-${i}`);
|
||||
if (pinDigits[i] !== undefined) {
|
||||
dot.textContent = '●';
|
||||
dot.classList.add('border-[#f97316]');
|
||||
dot.classList.remove('border-white/10');
|
||||
} else {
|
||||
dot.textContent = '';
|
||||
dot.classList.remove('border-[#f97316]');
|
||||
dot.classList.add('border-white/10');
|
||||
}
|
||||
}
|
||||
document.getElementById('pin-value').value = pinDigits.join('');
|
||||
const btn = document.getElementById('btn-pin-submit');
|
||||
btn.disabled = pinDigits.length !== 4;
|
||||
}
|
||||
|
||||
function pinPress(digit) {
|
||||
if (pinDigits.length < 4) {
|
||||
pinDigits.push(digit);
|
||||
updatePinDisplay();
|
||||
if (pinDigits.length === 4) {
|
||||
document.getElementById('btn-pin-submit').click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function pinBackspace() {
|
||||
pinDigits.pop();
|
||||
updatePinDisplay();
|
||||
}
|
||||
|
||||
function pinClear() {
|
||||
pinDigits = [];
|
||||
updatePinDisplay();
|
||||
}
|
||||
|
||||
// Suporte a teclado físico no PIN
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (!document.getElementById('form-pin').classList.contains('hidden')) {
|
||||
if (e.key >= '0' && e.key <= '9') pinPress(e.key);
|
||||
if (e.key === 'Backspace') pinBackspace();
|
||||
}
|
||||
});
|
||||
|
||||
<% if @pin_login %>
|
||||
document.addEventListener('DOMContentLoaded', () => switchTab('pin'));
|
||||
<% end %>
|
||||
</script>
|
||||
Reference in New Issue
Block a user