Fix: auth en NGINX, Tailwind local, soporte teclado y layout desktop
- Auth movida a NGINX (Basic Auth en htpasswd) para que fetch() del browser incluya credenciales automáticamente — resuelve categorías sin cargar y POST fallido - Tailwind CDN descargado al build del Docker y servido localmente — elimina dependencia externa en cada carga de página - Soporte de teclado físico en add.html (números, punto/coma, Backspace, Enter) - Layout centrado en desktop con max-w-md mx-auto en las tres páginas - Eliminada imagen decorativa externa y links de fonts duplicados Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
1db200343d
commit
1244235820
@@ -1,2 +1,5 @@
|
|||||||
# Credenciales locales — nunca commitear
|
# Credenciales locales — nunca commitear
|
||||||
pagos/api/config.php
|
pagos/api/config.php
|
||||||
|
|
||||||
|
# Assets generados (se descargan al hacer docker compose build)
|
||||||
|
pagos/js/tailwind.cdn.js
|
||||||
|
|||||||
+10
-2
@@ -1,6 +1,14 @@
|
|||||||
FROM php:8.2-fpm-alpine
|
FROM php:8.2-fpm-alpine
|
||||||
|
|
||||||
RUN apk add --no-cache sqlite sqlite-dev \
|
RUN apk add --no-cache sqlite sqlite-dev curl \
|
||||||
&& docker-php-ext-install pdo pdo_sqlite
|
&& docker-php-ext-install pdo pdo_sqlite \
|
||||||
|
&& curl -sL "https://cdn.tailwindcss.com?plugins=forms,container-queries" \
|
||||||
|
-o /tmp/tailwind.cdn.js
|
||||||
|
|
||||||
WORKDIR /var/www/html
|
WORKDIR /var/www/html
|
||||||
|
|
||||||
|
COPY docker/entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
CMD ["php-fpm"]
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./pagos:/var/www/html
|
- ./pagos:/var/www/html
|
||||||
- ./docker/nginx.conf:/etc/nginx/conf.d/default.conf
|
- ./docker/nginx.conf:/etc/nginx/conf.d/default.conf
|
||||||
|
- ./docker/htpasswd:/etc/nginx/.htpasswd:ro
|
||||||
depends_on:
|
depends_on:
|
||||||
- app
|
- app
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copiar tailwind.cdn.js al directorio servido si no existe
|
||||||
|
if [ ! -f /var/www/html/js/tailwind.cdn.js ]; then
|
||||||
|
cp /tmp/tailwind.cdn.js /var/www/html/js/tailwind.cdn.js
|
||||||
|
fi
|
||||||
|
exec "$@"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
root:$apr1$69HFcTHn$9hHiieirPfFe3M.lo87O21
|
||||||
@@ -5,6 +5,9 @@ server {
|
|||||||
|
|
||||||
resolver 127.0.0.11 valid=10s;
|
resolver 127.0.0.11 valid=10s;
|
||||||
|
|
||||||
|
auth_basic "Quiet Wealth";
|
||||||
|
auth_basic_user_file /etc/nginx/.htpasswd;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ =404;
|
try_files $uri $uri/ =404;
|
||||||
}
|
}
|
||||||
@@ -15,6 +18,8 @@ server {
|
|||||||
fastcgi_index index.php;
|
fastcgi_index index.php;
|
||||||
include fastcgi_params;
|
include fastcgi_params;
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
fastcgi_param PHP_AUTH_USER $remote_user;
|
||||||
|
fastcgi_param PHP_AUTH_PW $http_authorization;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ /db/ {
|
location ~ /db/ {
|
||||||
|
|||||||
+5
-7
@@ -4,10 +4,9 @@
|
|||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||||
<title>Nuevo Movimiento - Sanctuary</title>
|
<title>Nuevo Movimiento - Sanctuary</title>
|
||||||
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
<script src="js/tailwind.cdn.js"></script>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@300;400;500;600;700;800&display=swap" rel="stylesheet"/>
|
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@300;400;500;600;700;800&display=swap" rel="stylesheet"/>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
|
||||||
<script id="tailwind-config">
|
<script id="tailwind-config">
|
||||||
tailwind.config = {
|
tailwind.config = {
|
||||||
darkMode: "class",
|
darkMode: "class",
|
||||||
@@ -98,6 +97,7 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-background text-on-background min-h-screen flex flex-col">
|
<body class="bg-background text-on-background min-h-screen flex flex-col">
|
||||||
|
<div class="max-w-md mx-auto w-full flex flex-col flex-1 relative">
|
||||||
<!-- Top AppBar - Transactional Context (Shell Suppressed per mandate) -->
|
<!-- Top AppBar - Transactional Context (Shell Suppressed per mandate) -->
|
||||||
<header class="bg-[#f8faf9] dark:bg-[#191c1c] w-full top-0 px-6 py-4 flex justify-between items-center bg-transparent">
|
<header class="bg-[#f8faf9] dark:bg-[#191c1c] w-full top-0 px-6 py-4 flex justify-between items-center bg-transparent">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
@@ -174,9 +174,7 @@
|
|||||||
<span class="material-symbols-outlined" data-icon="check_circle">check_circle</span>
|
<span class="material-symbols-outlined" data-icon="check_circle">check_circle</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- Background Decorative Image (Sanctuary Aesthetic) -->
|
</div>
|
||||||
<div class="fixed top-0 right-0 -z-10 opacity-10">
|
|
||||||
<img alt="Calm plant leaves" class="w-64 h-64 object-cover rounded-full blur-xl translate-x-20 -translate-y-20" data-alt="Close-up of minimalist green tropical leaves with soft natural light and subtle shadows on a neutral background" src="https://lh3.googleusercontent.com/aida-public/AB6AXuD2h_FlCe-zmCdWpoDHshmlKT5cXI45RMNZ5-AgxCqZYUPAm3glpQE_wwgbqJ2nxoYSqTenbalJ4bQQBYGIiBfP5wtSkQt6hOJ-Gtl_cifGTAktK43DvjfdfiHDniAMFOJUG0cJmjTrd3nISnFPn-xNsg3CSTGPMIIW_n5H7HSUQcYBeDxWje7Wu8zDxapTTpMfci3Y4IeXwn-Wq94lmbuXPYPbpNtL19_R_6JNyujOMerXEhtUQm5nUIjIEG27anBV5TGHfaZabw"/>
|
|
||||||
<script src="js/ui.js"></script>
|
<script src="js/ui.js"></script>
|
||||||
<script src="js/add.js"></script>
|
<script src="js/add.js"></script>
|
||||||
</body></html>
|
</body></html>
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||||
<title>Historial - Quiet Wealth</title>
|
<title>Historial - Quiet Wealth</title>
|
||||||
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
<script src="js/tailwind.cdn.js"></script>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet"/>
|
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet"/>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||||
<script id="tailwind-config">
|
<script id="tailwind-config">
|
||||||
@@ -82,6 +82,7 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-background text-on-background min-h-screen pb-24">
|
<body class="bg-background text-on-background min-h-screen pb-24">
|
||||||
|
<div class="max-w-md mx-auto relative">
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<header class="bg-[#f8faf9] sticky top-0 z-40 px-6 py-4 flex items-center gap-4">
|
<header class="bg-[#f8faf9] sticky top-0 z-40 px-6 py-4 flex items-center gap-4">
|
||||||
@@ -108,13 +109,14 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- FAB agregar -->
|
<!-- FAB agregar -->
|
||||||
<div class="fixed bottom-6 right-6 z-50">
|
<div class="fixed bottom-6 right-6 z-50 md:right-[calc(50%-176px)]">
|
||||||
<button onclick="window.location.href='add.html'"
|
<button onclick="window.location.href='add.html'"
|
||||||
class="w-14 h-14 bg-primary text-white rounded-2xl shadow-lg shadow-primary/30 flex items-center justify-center active:scale-90 transition-transform">
|
class="w-14 h-14 bg-primary text-white rounded-2xl shadow-lg shadow-primary/30 flex items-center justify-center active:scale-90 transition-transform">
|
||||||
<span class="material-symbols-outlined">add</span>
|
<span class="material-symbols-outlined">add</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
<script src="js/ui.js"></script>
|
<script src="js/ui.js"></script>
|
||||||
<script src="js/historial.js"></script>
|
<script src="js/historial.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
+10
-11
@@ -3,10 +3,9 @@
|
|||||||
<html lang="en"><head>
|
<html lang="en"><head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||||
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
<script src="js/tailwind.cdn.js"></script>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet"/>
|
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet"/>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
|
||||||
<script id="tailwind-config">
|
<script id="tailwind-config">
|
||||||
tailwind.config = {
|
tailwind.config = {
|
||||||
darkMode: "class",
|
darkMode: "class",
|
||||||
@@ -89,6 +88,7 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-background text-on-background min-h-screen pb-32">
|
<body class="bg-background text-on-background min-h-screen pb-32">
|
||||||
|
<div class="max-w-md mx-auto relative">
|
||||||
<!-- TopAppBar -->
|
<!-- TopAppBar -->
|
||||||
<header class="bg-[#f8faf9] dark:bg-slate-950 docked full-width top-0 sticky z-40">
|
<header class="bg-[#f8faf9] dark:bg-slate-950 docked full-width top-0 sticky z-40">
|
||||||
<div class="flex justify-between items-center w-full px-6 py-4">
|
<div class="flex justify-between items-center w-full px-6 py-4">
|
||||||
@@ -218,19 +218,18 @@
|
|||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
<!-- BottomNavBar -->
|
<!-- BottomNavBar -->
|
||||||
<nav class="fixed bottom-0 left-0 w-full z-50 flex justify-around items-center px-8 pb-8 pt-4 bg-[#ffffff]/70 dark:bg-slate-900/70 backdrop-blur-xl shadow-[0px_-12px_32px_rgba(0,80,80,0.06)] rounded-t-[2rem]">
|
<nav class="fixed bottom-0 left-0 right-0 max-w-md mx-auto z-50 flex justify-around items-center px-8 pb-8 pt-4 bg-[#ffffff]/70 backdrop-blur-xl shadow-[0px_-12px_32px_rgba(0,80,80,0.06)] rounded-t-[2rem]">
|
||||||
<button class="flex items-center justify-center bg-[#006a6a] text-white rounded-2xl p-3 shadow-lg shadow-[#006a6a]/20 active:scale-90 transition-transform duration-300">
|
<button class="flex items-center justify-center bg-[#006a6a] text-white rounded-2xl p-3 shadow-lg shadow-[#006a6a]/20 active:scale-90 transition-transform duration-300">
|
||||||
<span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 1;">home</span>
|
<span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 1;">home</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="flex items-center justify-center text-[#3e4948] dark:text-slate-400 p-3 hover:text-[#006a6a] dark:hover:text-teal-300 active:scale-90 transition-transform duration-300" onclick="window.location.href='historial.html'">
|
<button class="flex items-center justify-center text-[#3e4948] p-3 hover:text-[#006a6a] active:scale-90 transition-transform duration-300" onclick="window.location.href='historial.html'">
|
||||||
<span class="material-symbols-outlined">history</span>
|
<span class="material-symbols-outlined">history</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="flex items-center justify-center text-[#3e4948] dark:text-slate-400 p-3 hover:text-[#006a6a] dark:hover:text-teal-300 active:scale-90 transition-transform duration-300">
|
<button class="flex items-center justify-center text-[#3e4948] p-3 hover:text-[#006a6a] active:scale-90 transition-transform duration-300" onclick="window.location.href='add.html'">
|
||||||
<span class="material-symbols-outlined">credit_card</span>
|
<span class="material-symbols-outlined">add_circle</span>
|
||||||
</button>
|
|
||||||
<button class="flex items-center justify-center text-[#3e4948] dark:text-slate-400 p-3 hover:text-[#006a6a] dark:hover:text-teal-300 active:scale-90 transition-transform duration-300">
|
|
||||||
<span class="material-symbols-outlined">person</span>
|
|
||||||
</button>
|
</button>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
<script src="js/ui.js"></script>
|
<script src="js/ui.js"></script>
|
||||||
<script src="js/dashboard.js"></script>
|
<script src="js/dashboard.js"></script>
|
||||||
</body></html>
|
</body></html>
|
||||||
+28
-14
@@ -43,25 +43,39 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
btnGasto.addEventListener('click', () => { selectedTipo = 'gasto'; updateTipoUI(); });
|
btnGasto.addEventListener('click', () => { selectedTipo = 'gasto'; updateTipoUI(); });
|
||||||
btnIngreso.addEventListener('click', () => { selectedTipo = 'ingreso'; updateTipoUI(); });
|
btnIngreso.addEventListener('click', () => { selectedTipo = 'ingreso'; updateTipoUI(); });
|
||||||
|
|
||||||
// Numpad logic
|
function applyInput(val) {
|
||||||
|
if (val === 'backspace') {
|
||||||
|
currentMonto = currentMonto.slice(0, -1);
|
||||||
|
if (currentMonto === '') currentMonto = "0";
|
||||||
|
} else if (/^[0-9]$/.test(val)) {
|
||||||
|
if (currentMonto === "0") {
|
||||||
|
currentMonto = val;
|
||||||
|
} else {
|
||||||
|
currentMonto += val;
|
||||||
|
}
|
||||||
|
} else if (val === '.') {
|
||||||
|
if (!currentMonto.includes('.')) currentMonto += '.';
|
||||||
|
}
|
||||||
|
montoEl.textContent = currentMonto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Numpad táctil
|
||||||
numpad.addEventListener('click', (e) => {
|
numpad.addEventListener('click', (e) => {
|
||||||
const btn = e.target.closest('button');
|
const btn = e.target.closest('button');
|
||||||
if (!btn) return;
|
if (!btn) return;
|
||||||
|
if (btn.querySelector('[data-icon="backspace"]')) {
|
||||||
const val = btn.textContent.trim() || btn.innerText.trim();
|
applyInput('backspace');
|
||||||
|
|
||||||
if (val === 'backspace' || btn.querySelector('[data-icon="backspace"]')) {
|
|
||||||
currentMonto = currentMonto.slice(0, -1);
|
|
||||||
if (currentMonto === '') currentMonto = "0";
|
|
||||||
} else {
|
} else {
|
||||||
if (currentMonto === "0" && val !== ".") {
|
applyInput(btn.textContent.trim());
|
||||||
currentMonto = val;
|
|
||||||
} else {
|
|
||||||
if (val === "." && currentMonto.includes(".")) return;
|
|
||||||
currentMonto += val;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
montoEl.textContent = currentMonto;
|
});
|
||||||
|
|
||||||
|
// Teclado físico (desktop)
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key >= '0' && e.key <= '9') applyInput(e.key);
|
||||||
|
else if (e.key === '.' || e.key === ',') applyInput('.');
|
||||||
|
else if (e.key === 'Backspace') applyInput('backspace');
|
||||||
|
else if (e.key === 'Enter') btnSave.click();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Guardar Movimiento
|
// Guardar Movimiento
|
||||||
|
|||||||
Reference in New Issue
Block a user