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,209 +1,209 @@
/**
* CacheManager - Gerenciador central do sistema de cache
* Coordena IndexedDB, sincronização e acesso aos dados
*/
class CacheManager {
constructor(config = {}) {
this.dbName = config.dbName || 'AcoCalcProDB';
this.version = config.version || 1;
this.db = null;
this.config = {
debug: config.debug || false,
autoSync: config.autoSync || false,
cacheExpiry: config.cacheExpiry || (7 * 24 * 60 * 60 * 1000), // 7 dias
...config
};
this.stores = [
'cantoneiras',
'barras',
'barras_chatas',
'barras_roscadas',
'tubos_circulares',
'tubos_rhs',
'chapas',
'perfis_i',
'perfis_w',
'perfis_hp',
'_metadata',
'_config'
];
}
/**
* Inicializa o IndexedDB
*/
async init() {
return new Promise((resolve, reject) => {
if (!window.indexedDB) {
console.warn('⚠️ IndexedDB não disponível - usando fallback para CSV');
resolve(false);
return;
}
const request = indexedDB.open(this.dbName, this.version);
request.onerror = () => {
console.error('❌ Erro ao abrir IndexedDB:', request.error);
reject(request.error);
};
request.onsuccess = () => {
this.db = request.result;
if (this.config.debug) {
console.log('✅ IndexedDB inicializado:', this.dbName);
}
resolve(true);
};
request.onupgradeneeded = (event) => {
const db = event.target.result;
// Criar stores para cada tipo de perfil
this.stores.forEach(storeName => {
if (!db.objectStoreNames.contains(storeName)) {
const store = db.createObjectStore(storeName, { keyPath: 'id' });
// Criar índices para busca rápida
if (storeName !== '_metadata' && storeName !== '_config') {
store.createIndex('nome', 'nome', { unique: false });
store.createIndex('tipo', 'tipo', { unique: false });
}
if (this.config.debug) {
console.log(`✅ Store criada: ${storeName}`);
}
}
});
};
});
}
/**
* Verifica saúde do cache
*/
async checkHealth() {
if (!this.db) {
return {
healthy: false,
error: 'Database not initialized'
};
}
try {
const stats = {};
for (const storeName of this.stores) {
if (storeName.startsWith('_')) continue;
const count = await this.count(storeName);
const metadata = await this.getMetadata(storeName);
stats[storeName] = {
count,
lastSync: metadata?.lastSync || null,
size: metadata?.size || 0
};
}
return {
healthy: true,
stats,
totalSize: Object.values(stats).reduce((sum, s) => sum + s.size, 0)
};
} catch (error) {
return {
healthy: false,
error: error.message
};
}
}
/**
* Limpa todo o cache
*/
async clearAll() {
if (!this.db) {
throw new Error('Database not initialized');
}
const promises = this.stores
.filter(s => !s.startsWith('_'))
.map(storeName => this.clear(storeName));
await Promise.all(promises);
if (this.config.debug) {
console.log('✅ Todo o cache foi limpo');
}
}
/**
* Conta registros em uma store
*/
async count(storeName) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([storeName], 'readonly');
const store = transaction.objectStore(storeName);
const request = store.count();
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
/**
* Limpa uma store específica
*/
async clear(storeName) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([storeName], 'readwrite');
const store = transaction.objectStore(storeName);
const request = store.clear();
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
}
/**
* Busca metadados de um tipo
*/
async getMetadata(tipo) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction(['_metadata'], 'readonly');
const store = transaction.objectStore('_metadata');
const request = store.get(tipo);
request.onsuccess = () => resolve(request.result || null);
request.onerror = () => reject(request.error);
});
}
/**
* Salva metadados de um tipo
*/
async setMetadata(tipo, metadata) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction(['_metadata'], 'readwrite');
const store = transaction.objectStore('_metadata');
const request = store.put({ tipo, ...metadata });
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
}
/**
* Retorna estatísticas de uso
*/
getStats() {
return this.checkHealth();
}
}
// Exportar para uso global
window.CacheManager = CacheManager;
console.log('✅ CacheManager carregado');
/**
* CacheManager - Gerenciador central do sistema de cache
* Coordena IndexedDB, sincronização e acesso aos dados
*/
class CacheManager {
constructor(config = {}) {
this.dbName = config.dbName || 'AcoCalcProDB';
this.version = config.version || 1;
this.db = null;
this.config = {
debug: config.debug || false,
autoSync: config.autoSync || false,
cacheExpiry: config.cacheExpiry || (7 * 24 * 60 * 60 * 1000), // 7 dias
...config
};
this.stores = [
'cantoneiras',
'barras',
'barras_chatas',
'barras_roscadas',
'tubos_circulares',
'tubos_rhs',
'chapas',
'perfis_i',
'perfis_w',
'perfis_hp',
'_metadata',
'_config'
];
}
/**
* Inicializa o IndexedDB
*/
async init() {
return new Promise((resolve, reject) => {
if (!window.indexedDB) {
console.warn('⚠️ IndexedDB não disponível - usando fallback para CSV');
resolve(false);
return;
}
const request = indexedDB.open(this.dbName, this.version);
request.onerror = () => {
console.error('❌ Erro ao abrir IndexedDB:', request.error);
reject(request.error);
};
request.onsuccess = () => {
this.db = request.result;
if (this.config.debug) {
console.log('✅ IndexedDB inicializado:', this.dbName);
}
resolve(true);
};
request.onupgradeneeded = (event) => {
const db = event.target.result;
// Criar stores para cada tipo de perfil
this.stores.forEach(storeName => {
if (!db.objectStoreNames.contains(storeName)) {
const store = db.createObjectStore(storeName, { keyPath: 'id' });
// Criar índices para busca rápida
if (storeName !== '_metadata' && storeName !== '_config') {
store.createIndex('nome', 'nome', { unique: false });
store.createIndex('tipo', 'tipo', { unique: false });
}
if (this.config.debug) {
console.log(`✅ Store criada: ${storeName}`);
}
}
});
};
});
}
/**
* Verifica saúde do cache
*/
async checkHealth() {
if (!this.db) {
return {
healthy: false,
error: 'Database not initialized'
};
}
try {
const stats = {};
for (const storeName of this.stores) {
if (storeName.startsWith('_')) continue;
const count = await this.count(storeName);
const metadata = await this.getMetadata(storeName);
stats[storeName] = {
count,
lastSync: metadata?.lastSync || null,
size: metadata?.size || 0
};
}
return {
healthy: true,
stats,
totalSize: Object.values(stats).reduce((sum, s) => sum + s.size, 0)
};
} catch (error) {
return {
healthy: false,
error: error.message
};
}
}
/**
* Limpa todo o cache
*/
async clearAll() {
if (!this.db) {
throw new Error('Database not initialized');
}
const promises = this.stores
.filter(s => !s.startsWith('_'))
.map(storeName => this.clear(storeName));
await Promise.all(promises);
if (this.config.debug) {
console.log('✅ Todo o cache foi limpo');
}
}
/**
* Conta registros em uma store
*/
async count(storeName) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([storeName], 'readonly');
const store = transaction.objectStore(storeName);
const request = store.count();
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
/**
* Limpa uma store específica
*/
async clear(storeName) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction([storeName], 'readwrite');
const store = transaction.objectStore(storeName);
const request = store.clear();
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
}
/**
* Busca metadados de um tipo
*/
async getMetadata(tipo) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction(['_metadata'], 'readonly');
const store = transaction.objectStore('_metadata');
const request = store.get(tipo);
request.onsuccess = () => resolve(request.result || null);
request.onerror = () => reject(request.error);
});
}
/**
* Salva metadados de um tipo
*/
async setMetadata(tipo, metadata) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction(['_metadata'], 'readwrite');
const store = transaction.objectStore('_metadata');
const request = store.put({ tipo, ...metadata });
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
}
/**
* Retorna estatísticas de uso
*/
getStats() {
return this.checkHealth();
}
}
// Exportar para uso global
window.CacheManager = CacheManager;
console.log('✅ CacheManager carregado');

View File

@@ -1,91 +1,91 @@
/**
* Application State Management
* Central state for the entire application
*/
// Main application state
export const appState = {
history: [],
favorites: [],
budgetItems: [],
currentSection: 'cev',
currentTheme: 'dark',
expertMode: false,
currentSidebarTab: 0
};
// User preferences (persisted to localStorage)
export const userPreferences = {
theme: 'dark',
colorScheme: 'default', // default, blue, green, purple, orange
fontSize: 'medium', // small, medium, large, xlarge
fontFamily: 'default' // default, modern, classic, mono
};
// Admin configuration
export const adminConfig = {
appName: 'SteelBase',
appSubtitle: 'Plataforma Técnica com Base de Dados de Materiais Brasileiros',
footerText: '© 2025 SteelBase v7.5 PROFESSIONAL EDITION - Plataforma Técnica com Base de Dados de Materiais Brasileiros',
themeDefault: 'escuro',
modeDefault: 'simples',
toolsVisibility: {
'cev': true,
'seletor': true,
'equivalencias': false,
'comparativo': false,
'parafusos': true,
'layout': true,
'parafuso-vs-solda': false,
'preaquecimento': true,
'dureza': true,
'charpy': true,
'certificado': false,
'ultrassom': false,
'area-pintura': true,
'consumo-tinta': true,
'galvanizacao': false,
'custo-pintura': true,
'secagem': false,
'inspecao-pintura': false,
'orcamento': true,
'peso-rigging': false,
'referencia': false
}
};
/**
* Update app state
* @param {string} key - State key
* @param {any} value - New value
*/
export function updateState(key, value) {
appState[key] = value;
}
/**
* Get state value
* @param {string} key - State key
* @returns {any} State value
*/
export function getState(key) {
return appState[key];
}
/**
* Update user preferences
* @param {string} key - Preference key
* @param {any} value - New value
*/
export function updatePreference(key, value) {
userPreferences[key] = value;
}
/**
* Get preference value
* @param {string} key - Preference key
* @returns {any} Preference value
*/
export function getPreference(key) {
return userPreferences[key];
}
/**
* Application State Management
* Central state for the entire application
*/
// Main application state
export const appState = {
history: [],
favorites: [],
budgetItems: [],
currentSection: 'cev',
currentTheme: 'dark',
expertMode: false,
currentSidebarTab: 0
};
// User preferences (persisted to localStorage)
export const userPreferences = {
theme: 'dark',
colorScheme: 'default', // default, blue, green, purple, orange
fontSize: 'medium', // small, medium, large, xlarge
fontFamily: 'default' // default, modern, classic, mono
};
// Admin configuration
export const adminConfig = {
appName: 'SteelBase',
appSubtitle: 'Plataforma Técnica com Base de Dados de Materiais Brasileiros',
footerText: '© 2025 SteelBase v7.5 PROFESSIONAL EDITION - Plataforma Técnica com Base de Dados de Materiais Brasileiros',
themeDefault: 'escuro',
modeDefault: 'simples',
toolsVisibility: {
'cev': true,
'seletor': true,
'equivalencias': false,
'comparativo': false,
'parafusos': true,
'layout': true,
'parafuso-vs-solda': false,
'preaquecimento': true,
'dureza': true,
'charpy': true,
'certificado': false,
'ultrassom': false,
'area-pintura': true,
'consumo-tinta': true,
'galvanizacao': false,
'custo-pintura': true,
'secagem': false,
'inspecao-pintura': false,
'orcamento': true,
'peso-rigging': false,
'referencia': false
}
};
/**
* Update app state
* @param {string} key - State key
* @param {any} value - New value
*/
export function updateState(key, value) {
appState[key] = value;
}
/**
* Get state value
* @param {string} key - State key
* @returns {any} State value
*/
export function getState(key) {
return appState[key];
}
/**
* Update user preferences
* @param {string} key - Preference key
* @param {any} value - New value
*/
export function updatePreference(key, value) {
userPreferences[key] = value;
}
/**
* Get preference value
* @param {string} key - Preference key
* @returns {any} Preference value
*/
export function getPreference(key) {
return userPreferences[key];
}

View File

@@ -1,86 +1,86 @@
/**
* LocalStorage Management
* Handles persistence of user preferences
*/
import { userPreferences } from './state.js';
const STORAGE_KEY = 'acoCalcPreferences';
/**
* Load preferences from localStorage
* @returns {boolean} Success status
*/
export function loadPreferences() {
try {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
const parsed = JSON.parse(saved);
Object.assign(userPreferences, parsed);
console.log('✅ Preferências carregadas:', userPreferences);
return true;
}
return false;
} catch (error) {
console.warn('⚠️ Não foi possível carregar preferências:', error);
return false;
}
}
/**
* Save preferences to localStorage
* @returns {boolean} Success status
*/
export function savePreferences() {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(userPreferences));
console.log('✅ Preferências salvas');
return true;
} catch (error) {
console.warn('⚠️ Não foi possível salvar preferências:', error);
return false;
}
}
/**
* Clear all preferences
* @returns {boolean} Success status
*/
export function clearPreferences() {
try {
localStorage.removeItem(STORAGE_KEY);
console.log('✅ Preferências limpas');
return true;
} catch (error) {
console.warn('⚠️ Não foi possível limpar preferências:', error);
return false;
}
}
/**
* Get storage size in bytes
* @returns {number} Size in bytes
*/
export function getStorageSize() {
try {
const data = localStorage.getItem(STORAGE_KEY);
return data ? new Blob([data]).size : 0;
} catch (error) {
return 0;
}
}
/**
* Check if localStorage is available
* @returns {boolean} Availability status
*/
export function isStorageAvailable() {
try {
const test = '__storage_test__';
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch (error) {
return false;
}
}
/**
* LocalStorage Management
* Handles persistence of user preferences
*/
import { userPreferences } from './state.js';
const STORAGE_KEY = 'acoCalcPreferences';
/**
* Load preferences from localStorage
* @returns {boolean} Success status
*/
export function loadPreferences() {
try {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
const parsed = JSON.parse(saved);
Object.assign(userPreferences, parsed);
console.log('✅ Preferências carregadas:', userPreferences);
return true;
}
return false;
} catch (error) {
console.warn('⚠️ Não foi possível carregar preferências:', error);
return false;
}
}
/**
* Save preferences to localStorage
* @returns {boolean} Success status
*/
export function savePreferences() {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(userPreferences));
console.log('✅ Preferências salvas');
return true;
} catch (error) {
console.warn('⚠️ Não foi possível salvar preferências:', error);
return false;
}
}
/**
* Clear all preferences
* @returns {boolean} Success status
*/
export function clearPreferences() {
try {
localStorage.removeItem(STORAGE_KEY);
console.log('✅ Preferências limpas');
return true;
} catch (error) {
console.warn('⚠️ Não foi possível limpar preferências:', error);
return false;
}
}
/**
* Get storage size in bytes
* @returns {number} Size in bytes
*/
export function getStorageSize() {
try {
const data = localStorage.getItem(STORAGE_KEY);
return data ? new Blob([data]).size : 0;
} catch (error) {
return 0;
}
}
/**
* Check if localStorage is available
* @returns {boolean} Availability status
*/
export function isStorageAvailable() {
try {
const test = '__storage_test__';
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch (error) {
return false;
}
}