counter-tool / index.html
hrmkmdtv's picture
On the output section in the publishing tab make the out follow this structure
ad17e13 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🌴 Project Configuration Tool</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<style>
.counter-btn {
transition: all 0.2s ease;
}
.counter-btn:hover {
transform: scale(1.1);
}
.tab-active {
border-bottom: 3px solid #22c55e;
color: #22c55e;
font-weight: 600;
}
.copy-btn {
transition: all 0.2s ease;
}
.copy-btn:hover {
background-color: #22c55e;
color: white;
}
body {
background-color: #f0fdf4;
}
.bg-tropical-light {
background-color: #dcfce7;
}
.bg-tropical-medium {
background-color: #bbf7d0;
}
.text-tropical-dark {
color: #166534;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8">
<h1 class="text-3xl font-bold text-center mb-8 text-gray-800">Multiplicative Counter Tool</h1>
<div class="flex flex-col lg:flex-row gap-8">
<!-- Left Panel -->
<div class="w-full lg:w-1/2 bg-tropical-light p-6 rounded-lg shadow-md border border-green-200">
<h2 class="text-xl font-semibold mb-4 text-gray-700">Project Configuring</h2>
<!-- Tab Navigation for Left Panel -->
<div class="flex border-b mb-4">
<button class="py-2 px-4 tab-active-left" data-format-left="construction">Construction</button>
<button class="py-2 px-4 text-gray-500" data-format-left="publishing">Publishing</button>
</div>
<div class="space-y-4" id="counter-container">
<!-- Elements will be added here -->
</div>
</div>
<!-- Right Panel -->
<div class="w-full lg:w-1/2 bg-tropical-light p-6 rounded-lg shadow-md border border-green-200">
<h2 class="text-xl font-semibold mb-4 text-gray-700">Output</h2>
<!-- Tab Navigation -->
<div class="flex border-b mb-4">
<button class="py-2 px-4 tab-active" data-format="format1">Construction</button>
<button class="py-2 px-4 text-gray-500" data-format="format2">Publishing</button>
</div>
<!-- Output Content -->
<div id="output-content" class="bg-gray-100 p-4 rounded-lg min-h-[200px]">
<div id="format1-output" class="space-y-2">
<!-- Format 1 output will be here -->
</div>
<div id="format2-output" class="space-y-2 hidden">
<!-- Format 2 output will be here -->
</div>
</div>
<div class="mt-4 flex justify-end">
<button id="copy-btn" class="copy-btn border border-blue-500 text-blue-500 px-4 py-2 rounded-lg flex items-center">
<i data-feather="copy" class="mr-2"></i> Copy to Clipboard
</button>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
feather.replace();
// Predefined elements for Construction format
const constructionElements = [
{ name: 'homes', label: 'Homes', value: 1, format1: 'Home', format2: 'Home(s)', isConstruction: true },
{ name: 'rooms', label: 'Rooms Per House', value: 1, format1: 'Rooms per Home', format2: 'Rooms per Home', isConstruction: true },
{ name: 'walls', label: 'Walls Per Room', value: 1, format1: 'Walls per Room', format2: 'Walls per Room', isConstruction: true },
{ name: 'bricks', label: 'Bricks Per Wall', value: 1, format1: 'Bricks per Wall', format2: 'Bricks per Wall', isConstruction: true },
{ name: 'total', label: 'Total Bricks', value: 1, format1: 'Total Bricks', format2: 'Total Bricks', isTotal: true, isConstruction: true }
];
// Predefined elements for Publishing format
const publishingElements = [
{ name: 'books', label: 'Books', value: 1, format1: 'Book', format2: 'Book', isPublishing: true },
{ name: 'chapters', label: 'Chapters per Book', value: 1, format1: 'Chapters per Book', format2: 'Chapters per Book', isPublishing: true },
{ name: 'pages', label: 'Pages (scenes) per Chapter', value: 1, format1: 'Pages per Chapter', format2: 'Pages per Chapter', isPublishing: true },
{ name: 'panels', label: 'Panels (moments) per Page', value: 1, format1: 'Panels per Page', format2: 'Panels per Page', isPublishing: true },
{ name: 'total_pub', label: 'Total Panels / Moments', value: 1, format1: 'Total Panels', format2: 'Total Panels / Moments', isTotal: true, isPublishing: true }
];
const counterContainer = document.getElementById('counter-container');
const addElementBtn = document.getElementById('add-element');
const format1Output = document.getElementById('format1-output');
const format2Output = document.getElementById('format2-output');
const copyBtn = document.getElementById('copy-btn');
const tabButtons = document.querySelectorAll('[data-format]');
let elements = [...constructionElements];
let currentLeftFormat = 'construction';
// Initialize with construction elements
updateLeftPanel();
// Left panel tab switching functionality
const leftTabButtons = document.querySelectorAll('[data-format-left]');
leftTabButtons.forEach(button => {
button.addEventListener('click', function() {
const format = this.getAttribute('data-format-left');
// Update active tab
leftTabButtons.forEach(btn => {
btn.classList.remove('tab-active-left', 'text-green-600');
btn.classList.add('text-gray-500');
});
this.classList.add('tab-active-left', 'text-green-600');
this.classList.remove('text-gray-500');
currentLeftFormat = format;
// Update elements based on selected format
if (format === 'construction') {
elements = [...constructionElements];
} else {
elements = [...publishingElements];
}
updateLeftPanel();
updateOutput();
});
});
function updateLeftPanel() {
counterContainer.innerHTML = '';
elements.forEach((element, index) => {
addCounterElement(element, index);
});
}
// Tab switching functionality
tabButtons.forEach(button => {
button.addEventListener('click', function() {
const format = this.getAttribute('data-format');
// Update active tab
tabButtons.forEach(btn => {
btn.classList.remove('tab-active', 'text-green-600');
btn.classList.add('text-gray-500');
});
this.classList.add('tab-active', 'text-green-600');
this.classList.remove('text-gray-500');
// Show correct output
if (format === 'format1') {
document.getElementById('format1-output').classList.remove('hidden');
document.getElementById('format2-output').classList.add('hidden');
} else {
document.getElementById('format1-output').classList.add('hidden');
document.getElementById('format2-output').classList.remove('hidden');
}
});
});
// Copy to clipboard functionality
copyBtn.addEventListener('click', function() {
const activeFormat = document.querySelector('[data-format].tab-active').getAttribute('data-format');
const outputElement = document.getElementById(`${activeFormat}-output`);
const textToCopy = Array.from(outputElement.children)
.map(child => child.textContent)
.join('\n');
navigator.clipboard.writeText(textToCopy).then(() => {
const originalText = this.innerHTML;
this.innerHTML = '<i data-feather="check" class="mr-2"></i> Copied!';
feather.replace();
setTimeout(() => {
this.innerHTML = originalText;
feather.replace();
}, 2000);
});
});
function addCounterElement(element, index) {
const counterDiv = document.createElement('div');
counterDiv.className = 'counter-item flex items-center justify-between p-3 rounded-lg';
counterDiv.dataset.index = index;
counterDiv.innerHTML = `
<div class="flex-1">
<span class="text-gray-700">${element.label}</span>
</div>
<div class="flex items-center">
<button class="counter-btn decrease w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center mr-2">
<i data-feather="minus" class="w-4 h-4"></i>
</button>
<span class="value-display w-10 text-center font-semibold">${element.value}</span>
<button class="counter-btn increase w-8 h-8 rounded-full bg-green-100 text-green-700 flex items-center justify-center ml-2 hover:bg-green-200">
<i data-feather="plus" class="w-4 h-4"></i>
</button>
</div>
${element.isCustom ? `
<button class="delete-btn ml-4 text-red-500 hover:text-red-700">
<i data-feather="trash-2" class="w-4 h-4"></i>
</button>
` : ''}
`;
counterContainer.appendChild(counterDiv);
feather.replace();
// Add event listeners for the buttons
const decreaseBtn = counterDiv.querySelector('.decrease');
const increaseBtn = counterDiv.querySelector('.increase');
const valueDisplay = counterDiv.querySelector('.value-display');
const deleteBtn = counterDiv.querySelector('.delete-btn');
decreaseBtn.addEventListener('click', () => {
if (elements[index].value > 1) {
elements[index].value--;
valueDisplay.textContent = elements[index].value;
updateOutput();
}
});
increaseBtn.addEventListener('click', () => {
elements[index].value++;
valueDisplay.textContent = elements[index].value;
updateOutput();
});
if (deleteBtn) {
deleteBtn.addEventListener('click', () => {
elements.splice(index, 1);
counterDiv.remove();
// Update indices for remaining elements
document.querySelectorAll('.counter-item').forEach((item, i) => {
item.dataset.index = i;
});
updateOutput();
});
}
}
function updateOutput() {
// Calculate total if needed
if (elements.some(el => el.isTotal)) {
const totalIndex = elements.findIndex(el => el.isTotal);
if (totalIndex !== -1) {
let calculatedTotal = 1;
for (let i = 0; i < totalIndex; i++) {
calculatedTotal *= elements[i].value;
}
elements[totalIndex].value = calculatedTotal;
// Update the display for the total element
const totalDisplay = document.querySelector(`.counter-item[data-index="${totalIndex}"] .value-display`);
if (totalDisplay) {
totalDisplay.textContent = calculatedTotal;
}
}
}
// Update format 1 output
format1Output.innerHTML = '';
elements.forEach(element => {
if (!element.isTotal) {
const outputLine = document.createElement('div');
outputLine.className = 'text-gray-700';
outputLine.textContent = `${element.value} ${element.format1}${element.value !== 1 ? 's' : ''}`;
format1Output.appendChild(outputLine);
}
});
// Add total if it exists
const totalElement = elements.find(el => el.isTotal);
if (totalElement) {
const totalLine = document.createElement('div');
totalLine.className = 'font-bold text-gray-800 mt-2 pt-2 border-t';
totalLine.textContent = `${totalElement.value} ${totalElement.format1}${totalElement.value !== 1 ? 's' : ''}`;
format1Output.appendChild(totalLine);
}
// Update format 2 output
format2Output.innerHTML = '';
elements.forEach(element => {
if (!element.isTotal) {
const outputLine = document.createElement('div');
outputLine.className = 'text-gray-700';
outputLine.textContent = `${element.value} ${element.format2}${element.value !== 1 ? 's' : ''}`;
format2Output.appendChild(outputLine);
}
});
// Add total if it exists
if (totalElement) {
const totalLine = document.createElement('div');
totalLine.className = 'font-bold text-gray-800 mt-2 pt-2 border-t';
totalLine.textContent = `${totalElement.value} ${totalElement.format2}${totalElement.value !== 1 ? 's' : ''}`;
format2Output.appendChild(totalLine);
}
}
// Initial output update
updateOutput();
// Add CSS for left panel tabs
const style = document.createElement('style');
style.textContent = `
.tab-active-left {
border-bottom: 3px solid #22c55e;
color: #22c55e;
font-weight: 600;
}
.counter-item {
background-color: #f0fdf4;
border: 1px solid #bbf7d0;
}
`;
document.head.appendChild(style);
});
</script>
</body>
</html>