import { AlertOutlined, BulbOutlined } from "@ant-design/icons"; import * as Sentry from "@sentry/react"; import { Button, FloatButton, Layout, Space, Spin } from "antd"; import { lazy, Suspense, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { Link, Route, Routes } from "react-router-dom"; import { createStructuredSelector } from "reselect"; import BreadCrumbs from "../../components/breadcrumbs/breadcrumbs.component.jsx"; import ConflictComponent from "../../components/conflict/conflict.component.jsx"; import ErrorBoundary from "../../components/error-boundary/error-boundary.component.jsx"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component.jsx"; import PrintCenterModalContainer from "../../components/print-center-modal/print-center-modal.container.jsx"; import ShopSubStatusComponent from "../../components/shop-sub-status/shop-sub-status.component.jsx"; import UpdateAlert from "../../components/update-alert/update-alert.component.jsx"; import WssStatusDisplayComponent from "../../components/wss-status-display/wss-status-display.component.jsx"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; import { useSocket } from "../../contexts/SocketIO/useSocket.js"; import { addAlerts } from "../../redux/application/application.actions.js"; import { selectAlerts } from "../../redux/application/application.selectors.js"; import { selectBodyshop, selectInstanceConflict } from "../../redux/user/user.selectors.js"; import InstanceRenderManager from "../../utils/instanceRenderMgr.js"; const SimplifiedPartsJobsPage = lazy(() => import("../simplified-parts-jobs/simplified-parts-jobs.page.jsx")); const SimplifiedPartsJobsDetailPage = lazy( () => import("../simplified-parts-jobs-detail/simplified-parts-jobs-detail.container.jsx") ); const ShopPage = lazy(() => import("../shop/shop.page.component.jsx")); const ShopVendorPageContainer = lazy(() => import("../shop-vendor/shop-vendor.page.container.jsx")); const EmailOverlayContainer = lazy(() => import("../../components/email-overlay/email-overlay.container.jsx")); const FeatureRequestPage = lazy(() => import("../feature-request/feature-request.page.jsx")); const JobCostingModal = lazy(() => import("../../components/job-costing-modal/job-costing-modal.container.jsx")); const ReportCenterModal = lazy(() => import("../../components/report-center-modal/report-center-modal.container.jsx")); const BillEnterModalContainer = lazy(() => import("../../components/bill-enter-modal/bill-enter-modal.container.jsx")); const Help = lazy(() => import("../help/help.page.jsx")); const { Content, Footer } = Layout; const mapStateToProps = createStructuredSelector({ conflict: selectInstanceConflict, bodyshop: selectBodyshop, alerts: selectAlerts }); const ALERT_FILE_URL = InstanceRenderManager({ imex: "https://images.imex.online/alerts/alerts-imex.json", rome: "https://images.imex.online/alerts/alerts-rome.json" }); const mapDispatchToProps = (dispatch) => ({ setAlerts: (alerts) => dispatch(addAlerts(alerts)) }); export function SimplifiedPartsPage({ conflict, bodyshop, alerts, setAlerts }) { const { t } = useTranslation(); const { socket, clientId } = useSocket(); const notification = useNotification(); // State to track displayed alerts const [displayedAlertIds, setDisplayedAlertIds] = useState([]); // Fetch displayed alerts from localStorage on mount useEffect(() => { const displayedAlerts = JSON.parse(localStorage.getItem("displayedAlerts") || "[]"); setDisplayedAlertIds(displayedAlerts); }, []); // Fetch alerts from the JSON file and dispatch to Redux store useEffect(() => { const fetchAlerts = async () => { try { const response = await fetch(ALERT_FILE_URL); const fetchedAlerts = await response.json(); setAlerts(fetchedAlerts); } catch (error) { console.warn("Error fetching alerts:", error.message); } }; fetchAlerts().catch((err) => `Error fetching Bodyshop Alerts: ${err?.message || ""}`); }, [setAlerts]); // Use useEffect to watch for new alerts useEffect(() => { if (alerts && Object.keys(alerts).length > 0) { // Convert the alerts object into an array const alertArray = Object.values(alerts); // Filter out alerts that have already been dismissed const newAlerts = alertArray.filter((alert) => !displayedAlertIds.includes(alert.id)); newAlerts.forEach((alert) => { // Display the notification notification.open({ key: "notification-alerts-" + alert.id, message: alert.message, description: alert.description, type: alert.type || "info", duration: 0, closable: true, onClose: () => { // When the notification is closed, update displayed alerts state and localStorage setDisplayedAlertIds((prevIds) => { const updatedIds = [...prevIds, alert.id]; localStorage.setItem("displayedAlerts", JSON.stringify(updatedIds)); return updatedIds; }); } }); }); } }, [alerts, displayedAlertIds, notification]); useEffect(() => { window.Canny("initChangelog", { appID: "680bd2c7ee501290377f6686", position: "top", align: "left", theme: "light" // options: light [default], dark, auto }); }, []); useEffect(() => { document.title = InstanceRenderManager({ imex: t("titles.imexonline"), rome: t("titles.romeonline") }); }, [t]); const AppRouteTable = ( } > }> } /> }> } /> }> } /> }> } /> } /> }> } /> ); let PageContent; if (conflict) PageContent = ; else if (bodyshop && bodyshop.sub_status !== "active") PageContent = ; else PageContent = AppRouteTable; const broadcastMessage = () => { if (socket && bodyshop && bodyshop.id) { console.log(`Broadcasting message to bodyshop ${bodyshop.id}:`); socket.emit("broadcast-to-bodyshop", bodyshop.id, `Hello from ${clientId}`); } }; return ( {/* */} } showDialog> {PageContent} ); } export default connect(mapStateToProps, mapDispatchToProps)(SimplifiedPartsPage);