parkflow-pro / components /parking-grid.js
Randux's picture
crea una app para control de estacionamiento, debe ajustarse al tamaño del estacionamiento es decir la cantidad de plazas disponibles o puestos debe ser configurable. debe trabajar con 3 modelos 🅿️ Diagrama de Proceso para Estacionamiento Inteligente
ba33f5d verified
Raw
History Blame Contribute Delete
5.21 kB
class ParkingGrid extends HTMLElement {
static get observedAttributes() {
return ['slots', 'slots-data'];
}
constructor() {
super();
this.slots = 20;
this.slotsData = Array(this.slots).fill(null);
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'slots') {
this.slots = parseInt(newValue) || 20;
this.render();
}
if (name === 'slots-data') {
try {
this.slotsData = JSON.parse(newValue) || Array(this.slots).fill(null);
this.render();
} catch (e) {
console.error('Error parsing slots data', e);
}
}
}
connectedCallback() {
this.attachShadow({ mode: 'open' });
this.render();
}
render() {
const slotSize = this.slots <= 30 ? 'min-w-[100px]' :
this.slots <= 50 ? 'min-w-[80px]' : 'min-w-[60px]';
this.shadowRoot.innerHTML = `
<style>
.parking-slot {
transition: all 0.2s ease;
}
.occupied {
position: relative;
overflow: hidden;
}
.occupied:after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0.2) 100%);
}
.slot-number {
position: absolute;
top: 4px;
left: 4px;
background: rgba(255,255,255,0.9);
border-radius: 4px;
padding: 0 4px;
font-size: 10px;
font-weight: bold;
}
.plate-number {
position: absolute;
bottom: 4px;
left: 0;
right: 0;
text-align: center;
font-size: 10px;
font-weight: bold;
color: white;
text-shadow: 0 1px 2px rgba(0,0,0,0.5);
}
</style>
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-3">
${Array.from({ length: this.slots }, (_, i) => {
const slotData = this.slotsData[i];
let bgColor = 'bg-gray-100';
let borderColor = 'border-gray-200';
let textColor = 'text-gray-800';
if (slotData) {
switch(slotData.type) {
case 'monthly-fixed':
bgColor = 'bg-green-100';
borderColor = 'border-green-300';
textColor = 'text-green-800';
break;
case 'monthly-rotating':
bgColor = 'bg-yellow-100';
borderColor = 'border-yellow-300';
textColor = 'text-yellow-800';
break;
case 'hourly':
bgColor = 'bg-red-100';
borderColor = 'border-red-300';
textColor = 'text-red-800';
break;
}
}
return `
<div class="parking-slot ${slotData ? 'occupied' : ''} ${bgColor} ${borderColor} border-2 rounded-md h-20 ${slotSize} relative cursor-pointer">
<span class="slot-number ${textColor}">${i + 1}</span>
${slotData ? `
<div class="absolute inset-0 flex items-center justify-center">
<i data-feather="${slotData.keyDeposit ? 'key' : 'car'}" class="h-6 w-6 ${textColor}"></i>
</div>
<span class="plate-number">${slotData.plateNumber}</span>
` : `
<div class="absolute inset-0 flex items-center justify-center">
<i data-feather="circle" class="h-6 w-6 text-gray-300"></i>
</div>
`}
</div>
`;
}).join('')}
</div>
`;
// Reemplazar íconos feather
const featherIcons = this.shadowRoot.querySelectorAll('[data-feather]');
featherIcons.forEach(icon => {
feather.replace(icon);
});
}
}
customElements.define('parking-grid', ParkingGrid);