upskill-event-manager/responsive-analysis.js
bengizmo 993a820a84 feat: Add comprehensive development artifacts to repository
- Add 26 documentation files including test reports, deployment guides, and troubleshooting documentation
- Include 3 CSV data files for trainer imports and user registration tracking
- Add 43 JavaScript test files covering mobile optimization, Safari compatibility, and E2E testing
- Include 18 PHP utility files for debugging, geocoding, and data analysis
- Add 12 shell scripts for deployment verification, user management, and database operations
- Update .gitignore with whitelist patterns for development files, documentation, and CSV data

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 12:26:11 -03:00

214 lines
No EOL
7.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const fs = require('fs');
const path = require('path');
class ResponsiveAnalyzer {
constructor() {
this.breakpoints = new Map();
this.responsivePatterns = [];
this.issues = [];
}
analyzeResponsiveDesign() {
console.log('📱 RESPONSIVE DESIGN ANALYSIS');
console.log('='.repeat(50));
const cssFiles = [
'./assets/css/hvac-common.css',
'./assets/css/hvac-dashboard.css',
'./assets/css/hvac-registration.css',
'./assets/css/hvac-certificates.css',
'./assets/css/hvac-email-attendees.css',
'./assets/css/hvac-event-summary.css',
'./assets/css/hvac-attendee-profile.css',
'./assets/css/hvac-mobile-nav.css'
];
cssFiles.forEach(file => {
if (fs.existsSync(file)) {
this.analyzeFile(file);
}
});
this.generateResponsiveReport();
}
analyzeFile(filePath) {
const content = fs.readFileSync(filePath, 'utf8');
const fileName = path.basename(filePath);
console.log(`\n🔍 ${fileName}:`);
// Extract media queries
const mediaQueries = this.extractMediaQueries(content);
if (mediaQueries.length > 0) {
console.log(` 📱 ${mediaQueries.length} media queries found`);
mediaQueries.forEach(mq => {
console.log(` ${mq.condition} - ${mq.rules} rules`);
// Track breakpoint usage
const breakpoint = mq.condition;
if (this.breakpoints.has(breakpoint)) {
this.breakpoints.set(breakpoint, this.breakpoints.get(breakpoint) + 1);
} else {
this.breakpoints.set(breakpoint, 1);
}
});
} else {
console.log(` ⚠️ No media queries`);
this.issues.push({
file: fileName,
issue: 'No responsive design',
severity: 'medium'
});
}
// Check for mobile-first vs desktop-first approach
const mobileFirst = content.includes('min-width');
const desktopFirst = content.includes('max-width');
if (mobileFirst && desktopFirst) {
console.log(` 📱 Mixed approach (both min-width and max-width)`);
} else if (mobileFirst) {
console.log(` 📱 Mobile-first approach (min-width)`);
} else if (desktopFirst) {
console.log(` 🖥️ Desktop-first approach (max-width)`);
}
// Check for flexible units
const flexibleUnits = {
'rem': (content.match(/\d+(\.\d+)?rem/g) || []).length,
'em': (content.match(/\d+(\.\d+)?em/g) || []).length,
'%': (content.match(/\d+(\.\d+)?%/g) || []).length,
'vw': (content.match(/\d+(\.\d+)?vw/g) || []).length,
'vh': (content.match(/\d+(\.\d+)?vh/g) || []).length,
'px': (content.match(/\d+px/g) || []).length
};
console.log(` 📏 Units usage:`, flexibleUnits);
// Check for responsive patterns
this.checkResponsivePatterns(content, fileName);
}
extractMediaQueries(content) {
const mediaRegex = /@media[^{]*\{([^{}]*\{[^}]*\}[^{}]*)*\}/g;
const queries = [];
let match;
while ((match = mediaRegex.exec(content)) !== null) {
const fullQuery = match[0];
const condition = fullQuery.match(/@media[^{]*/)[0];
const body = fullQuery.slice(condition.length);
const rules = (body.match(/[^{}]+\{[^}]*\}/g) || []).length;
queries.push({
condition: condition.trim(),
body: body,
rules: rules
});
}
return queries;
}
checkResponsivePatterns(content, fileName) {
const patterns = {
'Flexible Grid': /display:\s*(grid|flex)/g,
'Responsive Images': /max-width:\s*100%/g,
'Fluid Typography': /font-size:\s*calc\(/g,
'Container Queries': /@container/g,
'Responsive Spacing': /margin|padding.*clamp|margin|padding.*min|margin|padding.*max/g,
'Responsive Tables': /overflow-x:\s*auto/g
};
Object.entries(patterns).forEach(([pattern, regex]) => {
const matches = content.match(regex);
if (matches) {
console.log(`${pattern}: ${matches.length} instances`);
this.responsivePatterns.push({
file: fileName,
pattern: pattern,
count: matches.length
});
}
});
}
generateResponsiveReport() {
console.log('\n' + '='.repeat(80));
console.log('📋 RESPONSIVE DESIGN REPORT');
console.log('='.repeat(80));
// Breakpoint analysis
console.log('\n📱 BREAKPOINT USAGE:');
const sortedBreakpoints = Array.from(this.breakpoints.entries())
.sort(([,a], [,b]) => b - a);
sortedBreakpoints.forEach(([breakpoint, count]) => {
console.log(` ${breakpoint} - Used ${count} times`);
});
// Common breakpoints check
const standardBreakpoints = [
'(max-width: 768px)',
'(max-width: 480px)',
'(max-width: 1024px)',
'(min-width: 768px)',
'(min-width: 1024px)'
];
console.log('\n📐 BREAKPOINT CONSISTENCY:');
standardBreakpoints.forEach(bp => {
if (this.breakpoints.has(bp)) {
console.log(`${bp} - Standard breakpoint used`);
} else {
console.log(` ⚠️ ${bp} - Standard breakpoint not used`);
}
});
// Responsive patterns summary
console.log('\n🎨 RESPONSIVE PATTERNS:');
const patternSummary = new Map();
this.responsivePatterns.forEach(p => {
if (patternSummary.has(p.pattern)) {
patternSummary.set(p.pattern, patternSummary.get(p.pattern) + p.count);
} else {
patternSummary.set(p.pattern, p.count);
}
});
Array.from(patternSummary.entries()).forEach(([pattern, count]) => {
console.log(`${pattern}: ${count} total uses across files`);
});
// Issues summary
if (this.issues.length > 0) {
console.log('\n⚠ RESPONSIVE ISSUES:');
this.issues.forEach((issue, i) => {
console.log(` ${i + 1}. ${issue.file}: ${issue.issue}`);
});
}
// Recommendations
console.log('\n💡 RESPONSIVE RECOMMENDATIONS:');
if (!this.breakpoints.has('(max-width: 320px)')) {
console.log(' • Consider adding extra-small device support (320px)');
}
if (!patternSummary.has('Fluid Typography')) {
console.log(' • Consider implementing fluid typography with clamp()');
}
if (!patternSummary.has('Container Queries')) {
console.log(' • Consider using container queries for component-based responsive design');
}
console.log(' • Test on actual devices, not just browser resize');
console.log(' • Use relative units (rem, em, %) for better scalability');
console.log(' • Implement progressive enhancement approach');
}
}
const analyzer = new ResponsiveAnalyzer();
analyzer.analyzeResponsiveDesign();