import React, { useState, useEffect } from 'react'; import { Calendar, Sparkles, Bug, Zap, Shield, ChevronDown, ChevronUp } from 'lucide-react'; import ToolLayout from '../components/ToolLayout'; const ReleaseNotes = () => { const [releases, setReleases] = useState([]); const [loading, setLoading] = useState(true); const [expandedReleases, setExpandedReleases] = useState(new Set()); // Parse commit messages into user-friendly release notes const parseCommitMessage = (message) => { // Skip non-user-informative commits const skipPatterns = [ /^fix eslint/i, /^remove.*eslint/i, /^update.*package/i, /^add debug/i, /^fix.*dependency/i, /deployment/i, /^fix.*mismatch/i ]; if (skipPatterns.some(pattern => pattern.test(message))) { return null; } // Transform commit messages to user-friendly descriptions const transformations = [ { pattern: /feat.*invoice.*editor.*improvements/i, type: 'feature', title: 'Invoice Editor Major Update', description: 'Complete overhaul of Invoice Editor with currency system, PDF generation fixes, improved UI/UX, removed print functionality (use PDF download instead), streamlined preview toolbar, and comprehensive bug fixes' }, { pattern: /feat.*enhanced.*what.*new.*feature.*non_tools.*category.*global.*footer/i, type: 'feature', title: 'What\'s New Feature & Navigation Improvements', description: 'Added attractive "What\'s New" button to homepage, created NON_TOOLS category for better navigation organization, separated navigation items in sidebar and mobile menu, and implemented unified global footer across all pages' }, { pattern: /improve.*objecteditor.*postmantable.*ui\/ux/i, type: 'enhancement', title: 'Enhanced Object Editor & Table View', description: 'Improved user interface and experience with better JSON parsing, HTML rendering, and copy functionality' }, { pattern: /feat.*analytics.*mobile.*ui/i, type: 'feature', title: 'Mobile UI Improvements', description: 'Optimized interface for mobile devices with better analytics integration' }, { pattern: /feat.*seo.*gdpr/i, type: 'feature', title: 'SEO & Privacy Compliance', description: 'Comprehensive SEO optimization and GDPR compliance features for better discoverability and privacy protection' }, { pattern: /improve.*objecteditor.*tableeditor/i, type: 'enhancement', title: 'Enhanced Data Editors', description: 'Major improvements to Object Editor and new Table Editor with advanced data manipulation features' }, { pattern: /enhanced.*object.*editor.*fetch.*mobile/i, type: 'feature', title: 'Object Editor with Data Fetching', description: 'Added ability to fetch data from URLs directly in Object Editor with mobile-optimized interface' }, { pattern: /complete.*postman.*table.*view/i, type: 'feature', title: 'Postman-Style Table View', description: 'New professional table visualization with consistent design and advanced data exploration features' }, { pattern: /enhanced.*mindmap.*visualization/i, type: 'feature', title: 'Professional Mindmap Visualization', description: 'Beautiful mindmap interface for visualizing complex data structures with interactive navigation' }, { pattern: /add.*text.*length.*checker/i, type: 'feature', title: 'Text Analysis Tool', description: 'New comprehensive text analysis tool with length checking and detailed text statistics' }, { pattern: /fix.*php.*serialization.*long.*text/i, type: 'fix', title: 'PHP Serialization Improvements', description: 'Fixed PHP serialization handling and added support for long text fields in Visual Editor' }, { pattern: /enhanced.*developer.*tools.*ux/i, type: 'enhancement', title: 'Developer Tools UX Enhancement', description: 'Improved overall user experience with visual enhancements and better tool organization' } ]; for (const transform of transformations) { if (transform.pattern.test(message)) { return { type: transform.type, title: transform.title, description: transform.description }; } } // Fallback for unmatched patterns if (message.includes('🐛') || message.toLowerCase().includes('fix')) { return { type: 'fix', title: 'Bug Fixes', description: message.replace(/🐛|fix/gi, '').trim() }; } if (message.includes('✨') || message.toLowerCase().includes('feat')) { return { type: 'feature', title: 'New Feature', description: message.replace(/✨|feat:/gi, '').trim() }; } return null; }; // Get type icon and color const getTypeConfig = (type) => { const configs = { feature: { icon: , color: 'text-blue-600 dark:text-blue-400', bgColor: 'bg-blue-100 dark:bg-blue-900/20', label: 'New Feature' }, enhancement: { icon: , color: 'text-purple-600 dark:text-purple-400', bgColor: 'bg-purple-100 dark:bg-purple-900/20', label: 'Enhancement' }, fix: { icon: , color: 'text-green-600 dark:text-green-400', bgColor: 'bg-green-100 dark:bg-green-900/20', label: 'Bug Fix' }, security: { icon: , color: 'text-red-600 dark:text-red-400', bgColor: 'bg-red-100 dark:bg-red-900/20', label: 'Security' } }; return configs[type] || configs.enhancement; }; // Group releases by date const groupReleasesByDate = (releases) => { const grouped = {}; releases.forEach(release => { const date = new Date(release.date).toDateString(); if (!grouped[date]) { grouped[date] = []; } grouped[date].push(release); }); return grouped; }; const toggleRelease = (date) => { const newExpanded = new Set(expandedReleases); if (newExpanded.has(date)) { newExpanded.delete(date); } else { newExpanded.add(date); } setExpandedReleases(newExpanded); }; useEffect(() => { // Simulate fetching commit data (in real app, this would be an API call) const commitData = [ { hash: 'new2024', date: '2025-09-24T18:57:18+07:00', message: 'feat: Enhanced What\'s New feature with NON_TOOLS category and global footer' }, { hash: '21d0406e', date: '2025-09-24T14:05:10+07:00', message: 'Improve ObjectEditor and PostmanTable UI/UX' }, { hash: '57655410', date: '2025-09-24T01:15:20+07:00', message: 'feat: optimize analytics and mobile UI improvements' }, { hash: '2e67a2bc', date: '2025-09-24T00:12:28+07:00', message: 'feat: comprehensive SEO optimization and GDPR compliance' }, { hash: '977e784d', date: '2025-09-23T14:17:13+07:00', message: 'Improve ObjectEditor and Add TableEditor' }, { hash: 'e1c74e4a', date: '2025-09-21T16:33:28+07:00', message: '✨ Enhanced Object Editor with fetch data & mobile improvements' }, { hash: '12d45590', date: '2025-09-21T15:09:17+07:00', message: '🎯 Complete Postman-Style Table View with Consistent Design' }, { hash: '82d14622', date: '2025-09-21T07:09:33+07:00', message: '✨ Enhanced mindmap visualization with professional UI' }, { hash: '6f5bdf5f', date: '2025-08-21T23:45:46+07:00', message: 'Add Text Length Checker tool with comprehensive text analysis features' }, { hash: '65cc3bc5', date: '2025-08-21T23:19:22+07:00', message: 'Fix PHP serialization and add Long Text type to Visual Editor' }, { hash: '97459ea3', date: '2025-08-07T20:05:11+07:00', message: 'feat: Enhanced developer tools UX with visual improvements' } ]; const parsedReleases = commitData .map(commit => { const parsed = parseCommitMessage(commit.message); if (!parsed) return null; return { ...parsed, date: commit.date, hash: commit.hash }; }) .filter(Boolean); setReleases(parsedReleases); setLoading(false); // Auto-expand only the first (latest) release const groupedByDate = groupReleasesByDate(parsedReleases); const sortedDates = Object.keys(groupedByDate).sort((a, b) => new Date(b) - new Date(a)); const autoExpand = new Set(); if (sortedDates.length > 0) { autoExpand.add(sortedDates[0]); // Only expand the latest date } setExpandedReleases(autoExpand); }, []); const groupedReleases = groupReleasesByDate(releases); return (
{/* Header */}

What's New

Discover the latest features, improvements, and bug fixes that make your development workflow even better.

{loading ? (
) : (
{/* Timeline line */}
{Object.entries(groupedReleases) .sort(([a], [b]) => new Date(b) - new Date(a)) .map(([date, dayReleases], index) => { const isExpanded = expandedReleases.has(date); const releaseDate = new Date(date); const isRecent = (new Date() - releaseDate) < 7 * 24 * 60 * 60 * 1000; return (
{/* Timeline dot */}
{/* Date Header */} {/* Release Items */} {isExpanded && (
{dayReleases.map((release, index) => { const typeConfig = getTypeConfig(release.type); return (
{typeConfig.icon}
{typeConfig.label}

{release.title}

{typeConfig.label}

{release.description}

{new Date(release.date).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })} #{release.hash}
); })}
)}
); })}
)} {/* Footer */}

Stay tuned for more exciting updates and improvements!

); }; export default ReleaseNotes;