calculadora-textil / index.html
JymNils's picture
añade el dato de costos extras - Follow Up Deployment
a8560f6 verified
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calculadora de Costos Textiles</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.input-error {
border-color: #f87171;
background-color: #fee2e2;
}
.result-card {
transition: all 0.3s ease;
}
.result-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-4xl">
<div class="text-center mb-10">
<h1 class="text-3xl md:text-4xl font-bold text-indigo-700 mb-2">Calculadora Textil</h1>
<p class="text-gray-600">Calcula el costo total de tela y sublimación para tus proyectos</p>
</div>
<div class="bg-white rounded-xl shadow-md p-6 mb-8">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label for="fabricPrice" class="block text-sm font-medium text-gray-700 mb-1">
<i class="fas fa-ruler-combined text-indigo-500 mr-2"></i>Precio por m² de tela ($)
</label>
<div class="relative">
<input type="number" id="fabricPrice" min="0" step="0.01" value="25"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<span class="absolute right-3 top-2.5 text-gray-500">$/m²</span>
</div>
<p id="fabricError" class="text-red-500 text-xs mt-1 hidden">Ingrese un valor válido</p>
</div>
<div>
<label for="sublimationPrice" class="block text-sm font-medium text-gray-700 mb-1">
<i class="fas fa-fire text-indigo-500 mr-2"></i>Precio por m² de sublimación ($)
</label>
<div class="relative">
<input type="number" id="sublimationPrice" min="0" step="0.01" value="25"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<span class="absolute right-3 top-2.5 text-gray-500">$/m²</span>
</div>
<p id="sublimationError" class="text-red-500 text-xs mt-1 hidden">Ingrese un valor válido</p>
</div>
<div>
<label for="fabricArea" class="block text-sm font-medium text-gray-700 mb-1">
<i class="fas fa-square text-indigo-500 mr-2"></i>Metros cuadrados de tela por unidad
</label>
<div class="relative">
<input type="number" id="fabricArea" min="0" step="0.01" value="0.80"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<span class="absolute right-3 top-2.5 text-gray-500"></span>
</div>
<p id="areaError" class="text-red-500 text-xs mt-1 hidden">Ingrese un valor válido</p>
</div>
<div>
<label for="sublimationArea" class="block text-sm font-medium text-gray-700 mb-1">
<i class="fas fa-square text-indigo-500 mr-2"></i>Metros cuadrados de sublimación por unidad
</label>
<div class="relative">
<input type="number" id="sublimationArea" min="0" step="0.01" value="0.85"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<span class="absolute right-3 top-2.5 text-gray-500"></span>
</div>
<p id="sublimationAreaError" class="text-red-500 text-xs mt-1 hidden">Ingrese un valor válido</p>
</div>
<div class="relative">
<label for="quantity" class="block text-sm font-medium text-gray-700 mb-1">
<i class="fas fa-boxes text-indigo-500 mr-2"></i>Cantidad de unidades
</label>
<input type="number" id="quantity" min="1" value="10"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<span class="absolute right-3 top-8 text-gray-500">unidades</span>
</div>
<div>
<label for="sewingPrice" class="block text-sm font-medium text-gray-700 mb-1">
<i class="fas fa-needle text-indigo-500 mr-2"></i>Precio de costura por unidad ($)
</label>
<div class="relative">
<input type="number" id="sewingPrice" min="0" step="0.01" value="12"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<span class="absolute right-3 top-2.5 text-gray-500">$/unidad</span>
</div>
<p id="sewingError" class="text-red-500 text-xs mt-1 hidden">Ingrese un valor válido</p>
</div>
<div>
<label for="orderName" class="block text-sm font-medium text-gray-700 mb-1">
<i class="fas fa-tag text-indigo-500 mr-2"></i>Nombre del pedido
</label>
<input type="text" id="orderName" value="Pedido 1"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
</div>
<div>
<label for="extraCosts" class="block text-sm font-medium text-gray-700 mb-1">
<i class="fas fa-plus-circle text-indigo-500 mr-2"></i>Costos extras por unidad ($)
</label>
<div class="relative">
<input type="number" id="extraCosts" min="0" step="0.01" value="0"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<span class="absolute right-3 top-2.5 text-gray-500">$/unidad</span>
</div>
<p id="extraCostsError" class="text-red-500 text-xs mt-1 hidden">Ingrese un valor válido</p>
</div>
</div>
<div class="mt-6 flex justify-center">
<button id="calculateBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-2 px-6 rounded-lg transition duration-300 flex items-center">
<i class="fas fa-calculator mr-2"></i> Calcular Costos
</button>
</div>
</div>
<div id="resultsContainer" class="hidden w-full">
<h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-chart-line text-indigo-500 mr-2"></i> Resultados
</h2>
<div class="grid grid-cols-1">
<div class="result-card bg-white rounded-xl shadow-md p-6 border-l-4 border-indigo-500 w-full">
<h3 class="font-medium text-gray-700 mb-4 flex items-center">
<i class="fas fa-tshirt text-indigo-500 mr-2"></i> Costo por 1 unidad
</h3>
<div class="space-y-3">
<div class="flex justify-between">
<span class="text-gray-600">Costo tela (1 unidad):</span>
<span id="fabricCostSingle" class="font-medium">$0.00</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Costo sublimación (1 unidad):</span>
<span id="sublimationCostSingle" class="font-medium">$0.00</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Costo costura (1 unidad):</span>
<span id="sewingCostSingle" class="font-medium">$0.00</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Costos extras (1 unidad):</span>
<span id="extraCostsSingle" class="font-medium">$0.00</span>
</div>
<div class="border-t border-gray-200 my-2"></div>
<div class="flex justify-between">
<span class="text-gray-800 font-semibold">Total por 1 unidad:</span>
<span id="totalCostSingle" class="text-indigo-600 font-bold">$0.00</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Costo tela:</span>
<span id="fabricCostQuantity" class="font-medium">$0.00</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Costo sublimación:</span>
<span id="sublimationCostQuantity" class="font-medium">$0.00</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Costos extras:</span>
<span id="extraCostsQuantity" class="font-medium">$0.00</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Costo costura:</span>
<span id="sewingCostQuantity" class="font-medium">$0.00</span>
</div>
<div class="border-t border-gray-200 my-2"></div>
<div class="flex justify-between">
<span class="text-gray-800 font-semibold">Total por <span id="quantityDisplay">1</span> unidad(es):</span>
<span id="totalCostQuantity" class="text-indigo-600 font-bold text-lg">$0.00</span>
</div>
</div>
</div>
</div>
<div class="mt-6 bg-white rounded-xl shadow-md p-6 w-full">
<h3 class="font-medium text-gray-700 mb-4 flex items-center">
<i class="fas fa-history text-indigo-500 mr-2"></i> Historial (últimos 10)
</h3>
<div id="historyList" class="space-y-3">
<!-- History items will be added here -->
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Load history from localStorage
let calculationHistory = JSON.parse(localStorage.getItem('textileCalcHistory')) || [];
renderHistory();
const calculateBtn = document.getElementById('calculateBtn');
const resultsContainer = document.getElementById('resultsContainer');
// Input fields
const fabricPriceInput = document.getElementById('fabricPrice');
const sublimationPriceInput = document.getElementById('sublimationPrice');
const fabricAreaInput = document.getElementById('fabricArea');
const sublimationAreaInput = document.getElementById('sublimationArea');
const sewingPriceInput = document.getElementById('sewingPrice');
// Error messages
const fabricError = document.getElementById('fabricError');
const sublimationError = document.getElementById('sublimationError');
const areaError = document.getElementById('areaError');
const sublimationAreaError = document.getElementById('sublimationAreaError');
const sewingError = document.getElementById('sewingError');
// Result fields
const fabricCostSingle = document.getElementById('fabricCostSingle');
const sublimationCostSingle = document.getElementById('sublimationCostSingle');
const totalCostSingle = document.getElementById('totalCostSingle');
const fabricCostBulk = document.getElementById('fabricCostBulk');
const sublimationCostBulk = document.getElementById('sublimationCostBulk');
const totalCostBulk = document.getElementById('totalCostBulk');
calculateBtn.addEventListener('click', calculateCosts);
// Also calculate when pressing Enter in any input
[fabricPriceInput, sublimationPriceInput, fabricAreaInput, sublimationAreaInput].forEach(input => {
input.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
calculateCosts();
}
});
});
function calculateCosts() {
// Reset error states
resetErrors();
// Get values
const fabricPrice = parseFloat(fabricPriceInput.value);
const sublimationPrice = parseFloat(sublimationPriceInput.value);
const fabricArea = parseFloat(fabricAreaInput.value);
const sublimationArea = parseFloat(sublimationAreaInput.value);
const sewingPrice = parseFloat(sewingPriceInput.value);
const extraCosts = parseFloat(document.getElementById('extraCosts').value) || 0;
// Validate inputs
let isValid = true;
if (isNaN(fabricPrice) || fabricPrice < 0) {
fabricError.classList.remove('hidden');
fabricPriceInput.classList.add('input-error');
isValid = false;
}
if (isNaN(sublimationPrice) || sublimationPrice < 0) {
sublimationError.classList.remove('hidden');
sublimationPriceInput.classList.add('input-error');
isValid = false;
}
if (isNaN(fabricArea) || fabricArea <= 0) {
areaError.classList.remove('hidden');
fabricAreaInput.classList.add('input-error');
isValid = false;
}
if (isNaN(sublimationArea) || sublimationArea < 0) {
sublimationAreaError.classList.remove('hidden');
sublimationAreaInput.classList.add('input-error');
isValid = false;
}
if (isNaN(sewingPrice) || sewingPrice < 0) {
sewingError.classList.remove('hidden');
sewingPriceInput.classList.add('input-error');
isValid = false;
}
if (!isValid) return;
// Calculate costs
const fabricCostPerUnit = fabricPrice * fabricArea;
const sublimationCostPerUnit = sublimationPrice * sublimationArea;
const totalCostPerUnit = fabricCostPerUnit + sublimationCostPerUnit + sewingPrice + extraCosts;
const quantity = parseInt(document.getElementById('quantity').value) || 1;
document.getElementById('quantityDisplay').textContent = quantity;
const fabricCostForQuantity = fabricCostPerUnit * quantity;
const sublimationCostForQuantity = sublimationCostPerUnit * quantity;
const sewingCostForQuantity = sewingPrice * quantity;
const extraCostsForQuantity = extraCosts * quantity;
const totalCostForQuantity = totalCostPerUnit * quantity;
// Update UI with results
fabricCostSingle.textContent = `${fabricCostPerUnit.toFixed(2)}`;
sublimationCostSingle.textContent = `${sublimationCostPerUnit.toFixed(2)}`;
totalCostSingle.textContent = `${totalCostPerUnit.toFixed(2)}`;
document.getElementById('sewingCostSingle').textContent = `${sewingPrice.toFixed(2)}`;
document.getElementById('extraCostsSingle').textContent = `${extraCosts.toFixed(2)}`;
document.getElementById('fabricCostQuantity').textContent = `${fabricCostForQuantity.toFixed(2)}`;
document.getElementById('sublimationCostQuantity').textContent = `${sublimationCostForQuantity.toFixed(2)}`;
document.getElementById('sewingCostQuantity').textContent = `${sewingCostForQuantity.toFixed(2)}`;
document.getElementById('extraCostsQuantity').textContent = `${extraCostsForQuantity.toFixed(2)}`;
document.getElementById('totalCostQuantity').textContent = `${totalCostForQuantity.toFixed(2)}`;
// Add to history
const orderName = document.getElementById('orderName').value || 'Pedido sin nombre';
const calculation = {
date: new Date().toLocaleString(),
fabricPrice,
sublimationPrice,
fabricArea,
sublimationArea,
sewingPrice,
extraCosts,
quantity,
orderName,
totalCostPerUnit,
totalCostForQuantity
};
calculationHistory.unshift(calculation);
if (calculationHistory.length > 10) {
calculationHistory = calculationHistory.slice(0, 10);
}
localStorage.setItem('textileCalcHistory', JSON.stringify(calculationHistory));
renderHistory();
// Show results
resultsContainer.classList.remove('hidden');
// Smooth scroll to results
resultsContainer.scrollIntoView({ behavior: 'smooth' });
}
function renderHistory() {
const historyList = document.getElementById('historyList');
historyList.innerHTML = '';
if (calculationHistory.length === 0) {
historyList.innerHTML = '<p class="text-gray-500 text-center py-4">No hay cálculos recientes</p>';
return;
}
calculationHistory.forEach(item => {
const historyItem = document.createElement('div');
historyItem.className = 'bg-gray-50 rounded-lg p-3 border border-gray-200';
historyItem.innerHTML = `
<div class="flex justify-between items-start">
<div>
<span class="text-xs text-gray-500">${item.date}</span>
<div class="text-sm mt-1">
<span class="font-medium">${item.orderName}</span>
<span class="mx-2">•</span>
<span>${item.quantity} unidad(es)</span>
<span class="mx-2">•</span>
<span>${item.fabricArea}m² tela</span>
<span class="mx-2">•</span>
<span>${item.sublimationArea}m² sublim</span>
${item.extraCosts > 0 ? `<span class="mx-2">•</span><span>Extras: ${item.extraCosts.toFixed(2)}</span>` : ''}
</div>
</div>
<div class="text-right">
<div class="text-sm">Unidad: <span class="font-medium">${item.totalCostPerUnit.toFixed(2)}</span></div>
<div class="text-sm">Total: <span class="font-medium text-indigo-600">${item.totalCostForQuantity.toFixed(2)}</span></div>
</div>
</div>
`;
historyList.appendChild(historyItem);
});
}
function resetErrors() {
[fabricError, sublimationError, areaError, sublimationAreaError, sewingError].forEach(error => {
error.classList.add('hidden');
});
[fabricPriceInput, sublimationPriceInput, fabricAreaInput, sublimationAreaInput, sewingPriceInput].forEach(input => {
input.classList.remove('input-error');
});
}
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo2" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=JymNils/calculadora-textil" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p><p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=JymNils/calculadora-textil" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p><p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=JymNils/calculadora-textil2" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>