docs: implement Antigravity global rules

This commit is contained in:
2026-04-03 21:11:04 +00:00
parent 57ba9d1c5f
commit e8972e7107
83 changed files with 31408 additions and 31386 deletions

View File

@@ -1,230 +1,230 @@
/**
* CSV Manager - CRUD operations for CSV files
* Handles reading, parsing, editing, and saving CSV data
*/
/**
* Parse CSV text to array of objects
* @param {string} csvText - CSV content
* @returns {Array<object>} Parsed data
*/
export function parseCSV(csvText) {
const lines = csvText.trim().split('\n');
if (lines.length === 0) return [];
// Get headers
const headers = lines[0].split(',').map(h => h.trim());
// Parse rows
const data = [];
for (let i = 1; i < lines.length; i++) {
const values = lines[i].split(',').map(v => v.trim());
const row = {};
headers.forEach((header, index) => {
row[header] = values[index] || '';
});
data.push(row);
}
return data;
}
/**
* Convert array of objects to CSV text
* @param {Array<object>} data - Data array
* @returns {string} CSV text
*/
export function toCSV(data) {
if (data.length === 0) return '';
// Get headers from first object
const headers = Object.keys(data[0]);
// Create CSV lines
const lines = [headers.join(',')];
data.forEach(row => {
const values = headers.map(header => {
const value = row[header] || '';
// Escape commas and quotes
if (value.includes(',') || value.includes('"')) {
return `"${value.replace(/"/g, '""')}"`;
}
return value;
});
lines.push(values.join(','));
});
return lines.join('\n');
}
/**
* Load CSV file
* @param {string} filename - CSV filename
* @returns {Promise<Array<object>>} Parsed data
*/
export async function loadCSV(filename) {
try {
const response = await fetch(`BD/${filename}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const text = await response.text();
return parseCSV(text);
} catch (error) {
console.error(`Erro ao carregar ${filename}:`, error);
throw error;
}
}
/**
* Download CSV file
* @param {string} filename - Filename
* @param {string} csvText - CSV content
*/
export function downloadCSV(filename, csvText) {
const blob = new Blob([csvText], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
/**
* Get available CSV files
* @returns {Array<object>} List of CSV files with metadata
*/
export function getAvailableCSVFiles() {
return [
{
id: 'perfis_w',
name: 'Perfis W',
filename: 'perfis_w.csv',
description: 'Perfis de aço tipo W (vigas)',
icon: '🏗️'
},
{
id: 'perfis_i',
name: 'Perfis I',
filename: 'perfis_i.csv',
description: 'Perfis de aço tipo I',
icon: '🏗️'
},
{
id: 'cantoneiras',
name: 'Cantoneiras',
filename: 'cantoneiras.csv',
description: 'Cantoneiras de aço',
icon: '📐'
},
{
id: 'tubos_circulares',
name: 'Tubos Circulares',
filename: 'tubos_circulares.csv',
description: 'Tubos de seção circular',
icon: '⭕'
},
{
id: 'tubos_rhs',
name: 'Tubos RHS',
filename: 'tubos_rhs.csv',
description: 'Tubos retangulares/quadrados',
icon: '⬜'
},
{
id: 'chapas',
name: 'Chapas',
filename: 'chapas.csv',
description: 'Chapas de aço',
icon: '📄'
},
{
id: 'barras',
name: 'Barras',
filename: 'barras.csv',
description: 'Barras redondas',
icon: ''
},
{
id: 'eletrodos',
name: 'Eletrodos',
filename: 'eletrodos.csv',
description: 'Eletrodos de soldagem',
icon: '⚡'
},
{
id: 'parafusos',
name: 'Parafusos',
filename: 'parafusos.csv',
description: 'Parafusos estruturais',
icon: '🔩'
},
{
id: 'tintas',
name: 'Tintas',
filename: 'tintas.csv',
description: 'Tintas e revestimentos',
icon: '🎨'
},
{
id: 'acos_soldagem',
name: 'Aços - Soldagem',
filename: 'Tabela_Acos_Soldagem_Consumiveis.csv',
description: 'Relação aços e consumíveis',
icon: '🔥'
},
{
id: 'acos_pintura',
name: 'Aços - Pintura',
filename: 'Tabela_Acos_Pintura_Tintas.csv',
description: 'Relação aços e tintas',
icon: '🎨'
}
];
}
/**
* Validate CSV data
* @param {Array<object>} data - Data to validate
* @returns {object} Validation result
*/
export function validateCSVData(data) {
const errors = [];
if (!Array.isArray(data) || data.length === 0) {
errors.push('Dados vazios ou inválidos');
return { valid: false, errors };
}
// Check if all rows have same keys
const firstKeys = Object.keys(data[0]).sort();
for (let i = 1; i < data.length; i++) {
const keys = Object.keys(data[i]).sort();
if (JSON.stringify(keys) !== JSON.stringify(firstKeys)) {
errors.push(`Linha ${i + 1}: Colunas inconsistentes`);
}
}
// Check for empty required fields (id, nome)
data.forEach((row, index) => {
if (!row.id || row.id.trim() === '') {
errors.push(`Linha ${index + 2}: Campo 'id' vazio`);
}
if (!row.nome || row.nome.trim() === '') {
errors.push(`Linha ${index + 2}: Campo 'nome' vazio`);
}
});
return {
valid: errors.length === 0,
errors
};
}
/**
* CSV Manager - CRUD operations for CSV files
* Handles reading, parsing, editing, and saving CSV data
*/
/**
* Parse CSV text to array of objects
* @param {string} csvText - CSV content
* @returns {Array<object>} Parsed data
*/
export function parseCSV(csvText) {
const lines = csvText.trim().split('\n');
if (lines.length === 0) return [];
// Get headers
const headers = lines[0].split(',').map(h => h.trim());
// Parse rows
const data = [];
for (let i = 1; i < lines.length; i++) {
const values = lines[i].split(',').map(v => v.trim());
const row = {};
headers.forEach((header, index) => {
row[header] = values[index] || '';
});
data.push(row);
}
return data;
}
/**
* Convert array of objects to CSV text
* @param {Array<object>} data - Data array
* @returns {string} CSV text
*/
export function toCSV(data) {
if (data.length === 0) return '';
// Get headers from first object
const headers = Object.keys(data[0]);
// Create CSV lines
const lines = [headers.join(',')];
data.forEach(row => {
const values = headers.map(header => {
const value = row[header] || '';
// Escape commas and quotes
if (value.includes(',') || value.includes('"')) {
return `"${value.replace(/"/g, '""')}"`;
}
return value;
});
lines.push(values.join(','));
});
return lines.join('\n');
}
/**
* Load CSV file
* @param {string} filename - CSV filename
* @returns {Promise<Array<object>>} Parsed data
*/
export async function loadCSV(filename) {
try {
const response = await fetch(`BD/${filename}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const text = await response.text();
return parseCSV(text);
} catch (error) {
console.error(`Erro ao carregar ${filename}:`, error);
throw error;
}
}
/**
* Download CSV file
* @param {string} filename - Filename
* @param {string} csvText - CSV content
*/
export function downloadCSV(filename, csvText) {
const blob = new Blob([csvText], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
/**
* Get available CSV files
* @returns {Array<object>} List of CSV files with metadata
*/
export function getAvailableCSVFiles() {
return [
{
id: 'perfis_w',
name: 'Perfis W',
filename: 'perfis_w.csv',
description: 'Perfis de aço tipo W (vigas)',
icon: '🏗️'
},
{
id: 'perfis_i',
name: 'Perfis I',
filename: 'perfis_i.csv',
description: 'Perfis de aço tipo I',
icon: '🏗️'
},
{
id: 'cantoneiras',
name: 'Cantoneiras',
filename: 'cantoneiras.csv',
description: 'Cantoneiras de aço',
icon: '📐'
},
{
id: 'tubos_circulares',
name: 'Tubos Circulares',
filename: 'tubos_circulares.csv',
description: 'Tubos de seção circular',
icon: '⭕'
},
{
id: 'tubos_rhs',
name: 'Tubos RHS',
filename: 'tubos_rhs.csv',
description: 'Tubos retangulares/quadrados',
icon: '⬜'
},
{
id: 'chapas',
name: 'Chapas',
filename: 'chapas.csv',
description: 'Chapas de aço',
icon: '📄'
},
{
id: 'barras',
name: 'Barras',
filename: 'barras.csv',
description: 'Barras redondas',
icon: ''
},
{
id: 'eletrodos',
name: 'Eletrodos',
filename: 'eletrodos.csv',
description: 'Eletrodos de soldagem',
icon: '⚡'
},
{
id: 'parafusos',
name: 'Parafusos',
filename: 'parafusos.csv',
description: 'Parafusos estruturais',
icon: '🔩'
},
{
id: 'tintas',
name: 'Tintas',
filename: 'tintas.csv',
description: 'Tintas e revestimentos',
icon: '🎨'
},
{
id: 'acos_soldagem',
name: 'Aços - Soldagem',
filename: 'Tabela_Acos_Soldagem_Consumiveis.csv',
description: 'Relação aços e consumíveis',
icon: '🔥'
},
{
id: 'acos_pintura',
name: 'Aços - Pintura',
filename: 'Tabela_Acos_Pintura_Tintas.csv',
description: 'Relação aços e tintas',
icon: '🎨'
}
];
}
/**
* Validate CSV data
* @param {Array<object>} data - Data to validate
* @returns {object} Validation result
*/
export function validateCSVData(data) {
const errors = [];
if (!Array.isArray(data) || data.length === 0) {
errors.push('Dados vazios ou inválidos');
return { valid: false, errors };
}
// Check if all rows have same keys
const firstKeys = Object.keys(data[0]).sort();
for (let i = 1; i < data.length; i++) {
const keys = Object.keys(data[i]).sort();
if (JSON.stringify(keys) !== JSON.stringify(firstKeys)) {
errors.push(`Linha ${i + 1}: Colunas inconsistentes`);
}
}
// Check for empty required fields (id, nome)
data.forEach((row, index) => {
if (!row.id || row.id.trim() === '') {
errors.push(`Linha ${index + 2}: Campo 'id' vazio`);
}
if (!row.nome || row.nome.trim() === '') {
errors.push(`Linha ${index + 2}: Campo 'nome' vazio`);
}
});
return {
valid: errors.length === 0,
errors
};
}