Davidal07 commited on
Commit
7d80450
verified
1 Parent(s): 76c90f2

undefined - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +519 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Test
3
- emoji: 馃弳
4
- colorFrom: blue
5
- colorTo: yellow
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: test
3
+ emoji: 馃惓
4
+ colorFrom: gray
5
+ colorTo: purple
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,519 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Sistema de Gesti贸n de N煤meros de Parte</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .fade-in {
11
+ animation: fadeIn 0.3s ease-in-out;
12
+ }
13
+
14
+ @keyframes fadeIn {
15
+ from { opacity: 0; transform: translateY(10px); }
16
+ to { opacity: 1; transform: translateY(0); }
17
+ }
18
+
19
+ .feature-item:hover .delete-feature {
20
+ opacity: 1;
21
+ }
22
+
23
+ .delete-feature {
24
+ opacity: 0;
25
+ transition: opacity 0.2s ease;
26
+ }
27
+ </style>
28
+ </head>
29
+ <body class="bg-gray-100 min-h-screen">
30
+ <div class="container mx-auto px-4 py-8">
31
+ <div class="max-w-4xl mx-auto">
32
+ <!-- Header -->
33
+ <div class="bg-blue-600 text-white rounded-lg shadow-md p-6 mb-8">
34
+ <h1 class="text-3xl font-bold">Sistema de Gesti贸n de N煤meros de Parte</h1>
35
+ <p class="mt-2">Registro y administraci贸n de n煤meros de parte para la empresa</p>
36
+ </div>
37
+
38
+ <!-- Main Form -->
39
+ <div class="bg-white rounded-lg shadow-md p-6 mb-8">
40
+ <h2 class="text-2xl font-semibold text-gray-800 mb-6">Nuevo N煤mero de Parte</h2>
41
+
42
+ <form id="partForm" class="space-y-6">
43
+ <!-- Basic Information -->
44
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
45
+ <div>
46
+ <label for="partNumber" class="block text-sm font-medium text-gray-700 mb-1">N煤mero de Parte*</label>
47
+ <input type="text" id="partNumber" name="partNumber" required
48
+ class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
49
+ </div>
50
+
51
+ <div>
52
+ <label for="partType" class="block text-sm font-medium text-gray-700 mb-1">Tipo de Parte*</label>
53
+ <select id="partType" name="partType" required
54
+ class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
55
+ <option value="">Seleccione un tipo</option>
56
+ <option value="MGG">MGG</option>
57
+ <option value="Iniciador">Iniciador</option>
58
+ <option value="Naked">Naked</option>
59
+ </select>
60
+ </div>
61
+ </div>
62
+
63
+ <!-- Description -->
64
+ <div>
65
+ <label for="description" class="block text-sm font-medium text-gray-700 mb-1">Descripci贸n</label>
66
+ <textarea id="description" name="description" rows="3"
67
+ class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500"></textarea>
68
+ </div>
69
+
70
+ <!-- Dynamic Features Section -->
71
+ <div id="featuresSection" class="hidden fade-in">
72
+ <h3 class="text-lg font-medium text-gray-800 mb-4">Caracter铆sticas</h3>
73
+ <div id="defaultFeatures" class="space-y-4 mb-6"></div>
74
+
75
+ <!-- Add Custom Feature -->
76
+ <div class="flex items-center space-x-4">
77
+ <input type="text" id="newFeatureName" placeholder="Nombre de caracter铆stica"
78
+ class="flex-1 px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
79
+ <input type="text" id="newFeatureValue" placeholder="Valor"
80
+ class="flex-1 px-4 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
81
+ <button type="button" id="addFeatureBtn"
82
+ class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 transition">
83
+ <i class="fas fa-plus mr-2"></i>Agregar
84
+ </button>
85
+ </div>
86
+ </div>
87
+
88
+ <!-- Form Actions -->
89
+ <div class="flex justify-end space-x-4 pt-6 border-t border-gray-200">
90
+ <button type="reset"
91
+ class="px-6 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition">
92
+ <i class="fas fa-times mr-2"></i>Cancelar
93
+ </button>
94
+ <button type="submit"
95
+ class="px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition">
96
+ <i class="fas fa-save mr-2"></i>Guardar
97
+ </button>
98
+ </div>
99
+ </form>
100
+ </div>
101
+
102
+ <!-- Parts List -->
103
+ <div class="bg-white rounded-lg shadow-md p-6">
104
+ <h2 class="text-2xl font-semibold text-gray-800 mb-6">N煤meros de Parte Registrados</h2>
105
+
106
+ <div class="overflow-x-auto">
107
+ <table class="min-w-full divide-y divide-gray-200">
108
+ <thead class="bg-gray-50">
109
+ <tr>
110
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">N煤mero</th>
111
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tipo</th>
112
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Descripci贸n</th>
113
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Acciones</th>
114
+ </tr>
115
+ </thead>
116
+ <tbody id="partsList" class="bg-white divide-y divide-gray-200">
117
+ <!-- Parts will be loaded here -->
118
+ <tr>
119
+ <td colspan="4" class="px-6 py-4 text-center text-gray-500">No hay n煤meros de parte registrados</td>
120
+ </tr>
121
+ </tbody>
122
+ </table>
123
+ </div>
124
+ </div>
125
+ </div>
126
+ </div>
127
+
128
+ <!-- Part Details Modal -->
129
+ <div id="partDetailsModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50">
130
+ <div class="bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">
131
+ <div class="p-6">
132
+ <div class="flex justify-between items-center mb-4">
133
+ <h3 id="modalTitle" class="text-xl font-semibold text-gray-800">Detalles del N煤mero de Parte</h3>
134
+ <button id="closeModalBtn" class="text-gray-500 hover:text-gray-700">
135
+ <i class="fas fa-times"></i>
136
+ </button>
137
+ </div>
138
+
139
+ <div id="modalContent" class="space-y-4">
140
+ <!-- Content will be loaded here -->
141
+ </div>
142
+
143
+ <div class="flex justify-end space-x-4 pt-6 mt-6 border-t border-gray-200">
144
+ <button id="editPartBtn" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition">
145
+ <i class="fas fa-edit mr-2"></i>Editar
146
+ </button>
147
+ <button id="deletePartBtn" class="px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700 transition">
148
+ <i class="fas fa-trash mr-2"></i>Eliminar
149
+ </button>
150
+ </div>
151
+ </div>
152
+ </div>
153
+ </div>
154
+
155
+ <script>
156
+ // Default features for each part type
157
+ const defaultFeatures = {
158
+ 'MGG': [
159
+ { name: 'Material', value: '', required: true },
160
+ { name: 'Espesor', value: '', required: true },
161
+ { name: 'Color', value: '', required: true },
162
+ { name: 'Acabado', value: '', required: false }
163
+ ],
164
+ 'Iniciador': [
165
+ { name: 'Potencia', value: '', required: true },
166
+ { name: 'Voltaje', value: '', required: true },
167
+ { name: 'Temperatura', value: '', required: false }
168
+ ],
169
+ 'Naked': [
170
+ { name: 'Di谩metro', value: '', required: true },
171
+ { name: 'Longitud', value: '', required: true },
172
+ { name: 'Peso', value: '', required: false }
173
+ ]
174
+ };
175
+
176
+ // Sample data storage (in a real scenario, this would be a database)
177
+ let partsDatabase = [];
178
+
179
+ // DOM Elements
180
+ const partForm = document.getElementById('partForm');
181
+ const partTypeSelect = document.getElementById('partType');
182
+ const featuresSection = document.getElementById('featuresSection');
183
+ const defaultFeaturesContainer = document.getElementById('defaultFeatures');
184
+ const newFeatureName = document.getElementById('newFeatureName');
185
+ const newFeatureValue = document.getElementById('newFeatureValue');
186
+ const addFeatureBtn = document.getElementById('addFeatureBtn');
187
+ const partsList = document.getElementById('partsList');
188
+ const partDetailsModal = document.getElementById('partDetailsModal');
189
+ const closeModalBtn = document.getElementById('closeModalBtn');
190
+ const modalContent = document.getElementById('modalContent');
191
+ const editPartBtn = document.getElementById('editPartBtn');
192
+ const deletePartBtn = document.getElementById('deletePartBtn');
193
+
194
+ // Event Listeners
195
+ partTypeSelect.addEventListener('change', updateFeatures);
196
+ addFeatureBtn.addEventListener('click', addCustomFeature);
197
+ partForm.addEventListener('submit', savePart);
198
+ closeModalBtn.addEventListener('click', () => partDetailsModal.classList.add('hidden'));
199
+ editPartBtn.addEventListener('click', editPart);
200
+ deletePartBtn.addEventListener('click', deletePart);
201
+
202
+ // Initialize the app
203
+ function init() {
204
+ // Load parts from localStorage (simulating database)
205
+ const savedParts = localStorage.getItem('partsDatabase');
206
+ if (savedParts) {
207
+ partsDatabase = JSON.parse(savedParts);
208
+ updatePartsList();
209
+ }
210
+ }
211
+
212
+ // Update features based on selected part type
213
+ function updateFeatures() {
214
+ const selectedType = partTypeSelect.value;
215
+
216
+ if (!selectedType) {
217
+ featuresSection.classList.add('hidden');
218
+ return;
219
+ }
220
+
221
+ // Clear previous features
222
+ defaultFeaturesContainer.innerHTML = '';
223
+
224
+ // Add default features for selected type
225
+ defaultFeatures[selectedType].forEach(feature => {
226
+ const featureItem = document.createElement('div');
227
+ featureItem.className = 'feature-item bg-gray-50 p-4 rounded-md relative';
228
+
229
+ featureItem.innerHTML = `
230
+ <div class="flex items-center space-x-4">
231
+ <div class="flex-1">
232
+ <label class="block text-sm font-medium text-gray-700 mb-1">${feature.name}${feature.required ? '*' : ''}</label>
233
+ <input type="text" name="feature_${feature.name}" value="${feature.value}"
234
+ ${feature.required ? 'required' : ''}
235
+ class="w-full px-3 py-1 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
236
+ </div>
237
+ ${!feature.required ? `
238
+ <button type="button" class="delete-feature px-3 py-1 bg-red-500 text-white rounded-md hover:bg-red-600 transition"
239
+ onclick="this.closest('.feature-item').remove()">
240
+ <i class="fas fa-trash"></i>
241
+ </button>
242
+ ` : ''}
243
+ </div>
244
+ `;
245
+
246
+ defaultFeaturesContainer.appendChild(featureItem);
247
+ });
248
+
249
+ // Show features section
250
+ featuresSection.classList.remove('hidden');
251
+ }
252
+
253
+ // Add custom feature
254
+ function addCustomFeature() {
255
+ const name = newFeatureName.value.trim();
256
+ const value = newFeatureValue.value.trim();
257
+
258
+ if (!name) {
259
+ alert('Por favor ingrese un nombre para la caracter铆stica');
260
+ return;
261
+ }
262
+
263
+ const featureItem = document.createElement('div');
264
+ featureItem.className = 'feature-item bg-gray-50 p-4 rounded-md relative fade-in';
265
+
266
+ featureItem.innerHTML = `
267
+ <div class="flex items-center space-x-4">
268
+ <div class="flex-1">
269
+ <label class="block text-sm font-medium text-gray-700 mb-1">${name}</label>
270
+ <input type="text" name="feature_${name}" value="${value}"
271
+ class="w-full px-3 py-1 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
272
+ </div>
273
+ <button type="button" class="delete-feature px-3 py-1 bg-red-500 text-white rounded-md hover:bg-red-600 transition"
274
+ onclick="this.closest('.feature-item').remove()">
275
+ <i class="fas fa-trash"></i>
276
+ </button>
277
+ </div>
278
+ `;
279
+
280
+ defaultFeaturesContainer.appendChild(featureItem);
281
+
282
+ // Clear inputs
283
+ newFeatureName.value = '';
284
+ newFeatureValue.value = '';
285
+ }
286
+
287
+ // Save part to database
288
+ function savePart(e) {
289
+ e.preventDefault();
290
+
291
+ const formData = new FormData(partForm);
292
+ const partNumber = formData.get('partNumber');
293
+ const partType = formData.get('partType');
294
+ const description = formData.get('description');
295
+
296
+ // Collect features
297
+ const features = [];
298
+ const featureItems = defaultFeaturesContainer.querySelectorAll('.feature-item');
299
+
300
+ featureItems.forEach(item => {
301
+ const label = item.querySelector('label').textContent.replace('*', '');
302
+ const input = item.querySelector('input');
303
+ const value = input.value.trim();
304
+
305
+ if (value) {
306
+ features.push({
307
+ name: label,
308
+ value: value,
309
+ required: input.required
310
+ });
311
+ } else if (input.required) {
312
+ alert(`Por favor complete el campo requerido: ${label}`);
313
+ input.focus();
314
+ throw new Error('Required field missing');
315
+ }
316
+ });
317
+
318
+ // Create part object
319
+ const part = {
320
+ id: Date.now().toString(),
321
+ partNumber,
322
+ partType,
323
+ description,
324
+ features,
325
+ createdAt: new Date().toISOString(),
326
+ createdBy: 'Usuario Actual' // In a real app, this would be the logged in user
327
+ };
328
+
329
+ // Add to database
330
+ partsDatabase.push(part);
331
+ localStorage.setItem('partsDatabase', JSON.stringify(partsDatabase));
332
+
333
+ // Update UI
334
+ updatePartsList();
335
+ partForm.reset();
336
+ featuresSection.classList.add('hidden');
337
+
338
+ // Show success message
339
+ alert('N煤mero de parte guardado exitosamente!');
340
+ }
341
+
342
+ // Update parts list in UI
343
+ function updatePartsList() {
344
+ if (partsDatabase.length === 0) {
345
+ partsList.innerHTML = `
346
+ <tr>
347
+ <td colspan="4" class="px-6 py-4 text-center text-gray-500">No hay n煤meros de parte registrados</td>
348
+ </tr>
349
+ `;
350
+ return;
351
+ }
352
+
353
+ partsList.innerHTML = '';
354
+
355
+ partsDatabase.forEach(part => {
356
+ const row = document.createElement('tr');
357
+ row.className = 'hover:bg-gray-50';
358
+ row.innerHTML = `
359
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${part.partNumber}</td>
360
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
361
+ <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full
362
+ ${part.partType === 'MGG' ? 'bg-blue-100 text-blue-800' :
363
+ part.partType === 'Iniciador' ? 'bg-green-100 text-green-800' :
364
+ 'bg-purple-100 text-purple-800'}">
365
+ ${part.partType}
366
+ </span>
367
+ </td>
368
+ <td class="px-6 py-4 text-sm text-gray-500">${part.description || 'Sin descripci贸n'}</td>
369
+ <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
370
+ <button onclick="showPartDetails('${part.id}')" class="text-blue-600 hover:text-blue-900 mr-4">
371
+ <i class="fas fa-eye"></i> Ver
372
+ </button>
373
+ <button onclick="editPartFromList('${part.id}')" class="text-yellow-600 hover:text-yellow-900">
374
+ <i class="fas fa-edit"></i> Editar
375
+ </button>
376
+ </td>
377
+ `;
378
+ partsList.appendChild(row);
379
+ });
380
+ }
381
+
382
+ // Show part details in modal
383
+ function showPartDetails(partId) {
384
+ const part = partsDatabase.find(p => p.id === partId);
385
+ if (!part) return;
386
+
387
+ document.getElementById('modalTitle').textContent = `Detalles: ${part.partNumber}`;
388
+
389
+ let content = `
390
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
391
+ <div>
392
+ <h4 class="text-sm font-medium text-gray-500">N煤mero de Parte</h4>
393
+ <p class="mt-1 text-sm text-gray-900">${part.partNumber}</p>
394
+ </div>
395
+ <div>
396
+ <h4 class="text-sm font-medium text-gray-500">Tipo</h4>
397
+ <p class="mt-1 text-sm text-gray-900">${part.partType}</p>
398
+ </div>
399
+ <div>
400
+ <h4 class="text-sm font-medium text-gray-500">Fecha de Creaci贸n</h4>
401
+ <p class="mt-1 text-sm text-gray-900">${new Date(part.createdAt).toLocaleString()}</p>
402
+ </div>
403
+ <div>
404
+ <h4 class="text-sm font-medium text-gray-500">Creado por</h4>
405
+ <p class="mt-1 text-sm text-gray-900">${part.createdBy}</p>
406
+ </div>
407
+ </div>
408
+
409
+ <div class="mb-6">
410
+ <h4 class="text-sm font-medium text-gray-500">Descripci贸n</h4>
411
+ <p class="mt-1 text-sm text-gray-900">${part.description || 'Sin descripci贸n'}</p>
412
+ </div>
413
+
414
+ <div>
415
+ <h4 class="text-sm font-medium text-gray-500 mb-2">Caracter铆sticas</h4>
416
+ <div class="bg-gray-50 rounded-md p-4">
417
+ `;
418
+
419
+ if (part.features.length === 0) {
420
+ content += `<p class="text-sm text-gray-500">No hay caracter铆sticas definidas</p>`;
421
+ } else {
422
+ content += `<div class="grid grid-cols-1 md:grid-cols-2 gap-4">`;
423
+ part.features.forEach(feat => {
424
+ content += `
425
+ <div>
426
+ <h5 class="text-xs font-medium text-gray-500">${feat.name}</h5>
427
+ <p class="text-sm text-gray-900">${feat.value}</p>
428
+ </div>
429
+ `;
430
+ });
431
+ content += `</div>`;
432
+ }
433
+
434
+ content += `</div></div>`;
435
+
436
+ modalContent.innerHTML = content;
437
+ editPartBtn.setAttribute('data-part-id', partId);
438
+ deletePartBtn.setAttribute('data-part-id', partId);
439
+ partDetailsModal.classList.remove('hidden');
440
+ }
441
+
442
+ // Edit part from list
443
+ function editPartFromList(partId) {
444
+ const part = partsDatabase.find(p => p.id === partId);
445
+ if (!part) return;
446
+
447
+ // Fill form with part data
448
+ document.getElementById('partNumber').value = part.partNumber;
449
+ document.getElementById('partType').value = part.partType;
450
+ document.getElementById('description').value = part.description || '';
451
+
452
+ // Trigger change event to load features
453
+ const event = new Event('change');
454
+ partTypeSelect.dispatchEvent(event);
455
+
456
+ // Wait for features to load
457
+ setTimeout(() => {
458
+ // Clear existing features
459
+ defaultFeaturesContainer.innerHTML = '';
460
+
461
+ // Add part features
462
+ part.features.forEach(feature => {
463
+ const isDefault = defaultFeatures[part.partType].some(f => f.name === feature.name);
464
+
465
+ const featureItem = document.createElement('div');
466
+ featureItem.className = 'feature-item bg-gray-50 p-4 rounded-md relative fade-in';
467
+
468
+ featureItem.innerHTML = `
469
+ <div class="flex items-center space-x-4">
470
+ <div class="flex-1">
471
+ <label class="block text-sm font-medium text-gray-700 mb-1">${feature.name}${feature.required ? '*' : ''}</label>
472
+ <input type="text" name="feature_${feature.name}" value="${feature.value}"
473
+ ${feature.required ? 'required' : ''}
474
+ class="w-full px-3 py-1 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
475
+ </div>
476
+ ${!feature.required ? `
477
+ <button type="button" class="delete-feature px-3 py-1 bg-red-500 text-white rounded-md hover:bg-red-600 transition"
478
+ onclick="this.closest('.feature-item').remove()">
479
+ <i class="fas fa-trash"></i>
480
+ </button>
481
+ ` : ''}
482
+ </div>
483
+ `;
484
+
485
+ defaultFeaturesContainer.appendChild(featureItem);
486
+ });
487
+
488
+ // Show features section
489
+ featuresSection.classList.remove('hidden');
490
+
491
+ // Scroll to form
492
+ document.querySelector('form').scrollIntoView({ behavior: 'smooth' });
493
+ }, 100);
494
+ }
495
+
496
+ // Edit part (from modal)
497
+ function editPart() {
498
+ const partId = this.getAttribute('data-part-id');
499
+ partDetailsModal.classList.add('hidden');
500
+ editPartFromList(partId);
501
+ }
502
+
503
+ // Delete part
504
+ function deletePart() {
505
+ if (!confirm('驴Est谩 seguro que desea eliminar este n煤mero de parte?')) return;
506
+
507
+ const partId = this.getAttribute('data-part-id');
508
+ partsDatabase = partsDatabase.filter(p => p.id !== partId);
509
+ localStorage.setItem('partsDatabase', JSON.stringify(partsDatabase));
510
+
511
+ partDetailsModal.classList.add('hidden');
512
+ updatePartsList();
513
+ }
514
+
515
+ // Initialize the app
516
+ init();
517
+ </script>
518
+ <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=Davidal07/test" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
519
+ </html>