Files
dewedev/src/components/NavigationConfirmModal.js
dwindown 3a475e9df2 feat: WCAG AA accessibility, code splitting, responsive ads layout
- Add React.lazy code splitting for all 15 tool pages
- Fix WCAG AA contrast issues (304 text color fixes)
- Add ARIA labels and aria-expanded to navigation buttons
- Add aria-live for error announcements in tools
- Implement responsive ad layout:
  - Desktop (≥1280px): Right sidebar with 3 ad units
  - Tablet (1024-1279px): Bottom section with 3 horizontal units
  - Mobile (<1024px): Fixed bottom banner
- Add TabletAdSection component for tablet ad placement
- Integrate Onidel affiliate partnership
- Update all Adsterra domains to solutionbiologyisle.com
- Add release notes for 2026-02-18 updates
2026-02-18 18:57:31 +07:00

116 lines
4.5 KiB
JavaScript

import React from 'react';
import { AlertTriangle } from 'lucide-react';
const NavigationConfirmModal = ({ isOpen, onConfirm, onCancel, targetPath, hasData }) => {
if (!isOpen) return null;
const getDataSummary = () => {
try {
const invoiceData = localStorage.getItem('currentInvoice');
const objectData = localStorage.getItem('objectEditorData');
const tableData = localStorage.getItem('tableEditorData');
const summary = [];
if (invoiceData) {
const parsed = JSON.parse(invoiceData);
if (parsed.invoiceNumber) summary.push(`Invoice #${parsed.invoiceNumber}`);
if (parsed.company?.name) summary.push(`Company information (${parsed.company.name})`);
if (parsed.client?.name) summary.push(`Client information (${parsed.client.name})`);
if (parsed.items?.length > 0) summary.push(`${parsed.items.length} line items`);
}
if (objectData) {
const parsed = JSON.parse(objectData);
if (parsed && Object.keys(parsed).length > 0) {
summary.push(`Object data with ${Object.keys(parsed).length} properties`);
}
}
if (tableData) {
const parsed = JSON.parse(tableData);
if (parsed && parsed.length > 0) {
summary.push(`Table data with ${parsed.length} rows`);
}
}
return summary;
} catch (error) {
return ['Unsaved data'];
}
};
const dataSummary = getDataSummary();
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full overflow-hidden">
{/* Header */}
<div className="px-6 py-4 border-b border-gray-200 dark:border-gray-700 bg-amber-50 dark:bg-amber-900/20">
<div className="flex items-center gap-3">
<div className="flex-shrink-0">
<AlertTriangle className="h-6 w-6 text-amber-600 dark:text-amber-400" />
</div>
<div>
<h3 className="text-lg font-semibold text-amber-900 dark:text-amber-100">
Confirm Navigation
</h3>
<p className="text-sm text-amber-700 dark:text-amber-300">
You have unsaved data that will be lost
</p>
</div>
</div>
</div>
{/* Content */}
<div className="px-6 py-4">
<p className="text-gray-700 dark:text-gray-300 mb-4">
You currently have unsaved data that will be lost if you leave this page. Are you sure you want to continue?
</p>
{dataSummary.length > 0 && (
<div className="bg-gray-50 dark:bg-gray-700 rounded-md p-3 mb-4">
<p className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
You currently have:
</p>
<ul className="text-sm text-gray-600 dark:text-gray-600 space-y-1">
{dataSummary.map((item, index) => (
<li key={index} className="flex items-center">
<span className="w-1.5 h-1.5 bg-amber-500 rounded-full mr-2 flex-shrink-0"></span>
{item}
</li>
))}
</ul>
</div>
)}
<div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-md p-3">
<p className="text-blue-800 dark:text-blue-200 text-sm">
<strong>Tip:</strong> Consider saving or exporting your current work before proceeding.
</p>
</div>
</div>
{/* Footer */}
<div className="px-6 py-4 bg-gray-50 dark:bg-gray-700 border-t border-gray-200 dark:border-gray-600 flex justify-end gap-3">
<button
onClick={onCancel}
className="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-600 border border-gray-300 dark:border-gray-500 rounded-md hover:bg-gray-50 dark:hover:bg-gray-500 transition-colors"
>
Cancel
</button>
<button
onClick={onConfirm}
className="px-4 py-2 text-sm font-medium text-white bg-amber-600 hover:bg-amber-700 rounded-md transition-colors flex items-center gap-2"
>
<AlertTriangle className="h-4 w-4" />
Continue & Lose Data
</button>
</div>
</div>
</div>
);
};
export default NavigationConfirmModal;