Rapport-Mobileapp/src/pages/Dashboard.jsx

486 lines
17 KiB
JavaScript
Executable File

import React, { useEffect, useState, useContext } from "react";
import { Link, useNavigate, useLocation } from "react-router-dom";
import { Container, Row, Col, Card, Button } from "react-bootstrap";
import Swiper from "react-id-swiper";
import "swiper/css/bundle";
import "swiper/bundle";
//Services
import dashboardService from "../services/Dashboard";
import contestServices from "../services/ContestServices";
import authService from "../services/Auth";
//Components
import PageComponent from "../components/PageComponent/PageComponent";
import PerformanceStatsContainer from "../components/DashboardPerformanceStats/PerformanceStatsContainer";
import PlaceholderCard from "../components/PlaceholderCard/PlaceholderCard";
import IconWrapper from "../components/IconWrapper/IconWrapper";
import UploadFile from "../components/UploadFile/UploadFile2";
import DashboardMagazinesContainer from "../components/DashboardMagazines/DashboardMagazinesContainer";
import DashboardContestsContainer from "../components/Contests/DashboardContestsContainer";
import CustomIcon from "../components/CustomIcon/CustomIcon";
import AppVersionUpdateModal from "../components/UI/AppVersionCheckAndUpdate/AppVersionUpdateModal";
import CustomImage from "../components/UI/CustomImage/CustomImage";
import MyCustomImage from "../components/UI/CustomImage/MyCustomImage";
import DashboardCompetitionContestsContainer from "../components/CompetitionContests/DashboardCompetitionContestsContainer";
import DashboardBanner from "../components/DashboardBanner/DashboardBanner";
import DashboardAdvertiseModal from "../components/DashboardAdvertiseModal/DashboardAdvertiseModal";
import OverlayNotificationModal from "../components/Notifications/OverlayNotificationModal";
import DashboardCampaignsContainer from "../components/DashboardCampaigns/DashboardCampaignsContainer";
//API
import notificationServices from "../services/NotificationServices";
//COntext
import AppContext from "../AppContext";
import { App as CapacitorApp } from "@capacitor/app";
function Dashboard() {
// console.log("Dashboard executed...");
const navigate = useNavigate();
const {getNotificationStats} = useContext(AppContext)
const location = useLocation();
const [wallBanners, setWallBanners] = useState([]);
const [otherBanners, setOtherBanners] = useState([]);
const [popupBanners, setPopupBanners] = useState([]);
const [appUpdatedInfo, setAppUpdatedInfo] = useState(null);
const [loadingBanner, setLoadingBanner] = useState(true);
const [loadingAppInfo, setLoadingAppInfo] = useState(true);
const [showAppVersionUpdateModal, setShowAppVersionUpdateModal] =
useState(false);
const [showDashboardAdvertisementModal, setShowDashboardAdvertisementModal] =
useState(false);
/** Unread overlay notifications; first item is shown in OverlayNotificationModal */
const [overlayNotificationQueue, setOverlayNotificationQueue] = useState([]);
function handleLogout() {
localStorage.clear();
navigate("/");
}
// App Version Update Confirmation Modal close
const handleCloseAppVersionUpdateModal = () => {
// console.log("Closing the modal");
setShowAppVersionUpdateModal(false);
};
//App Version Update Confirmation Modal Open
const handleShowAppVersionUpdateModal = () => {
setShowAppVersionUpdateModal(true);
// console.log("Opening the modal");
};
// Dashboard Advertisement Modal close
const handleCloseDashboardAdvertisementModal = () => {
// console.log("Closing the modal");
setShowDashboardAdvertisementModal(false);
};
//Dashboard Advertisement Modal Open
const handleShowDashboardAdvertisementModal = () => {
setShowDashboardAdvertisementModal(true);
// console.log("Opening the modal");
};
async function appInfoFromServer(data) {
// console.log(
// "async function appInfoFromServer called in Dashboard.jsx = ",
// JSON.stringify(data)
// );
// console.log("I am executed before CapacitorApp.getInfo()...");
const currentAppInfo = await CapacitorApp.getInfo();
// console.log("-- Outer currentAppInfo = ", JSON.stringify(currentAppInfo));
// console.log("I am executed after CapacitorApp.getInfo()...");
setLoadingAppInfo(true);
authService
.appInfoFromServer(data)
.then((res) => {
console.log("appInfoFromServer called == ", JSON.stringify(res.data));
if (res.data.status === "success") {
// console.log(
// "res from appInfoFromServer on SUCCESS =",
// JSON.stringify(res)
// );
const app_info = res.data?.data?.app_info;
// console.log(
// "-- currentAppInfo inside appInfoFromServer success = ",
// JSON.stringify(currentAppInfo)
// );
setAppUpdatedInfo(app_info);
const appCurrentVersion = parseFloat(
currentAppInfo?.version
// authService.getAppCurrentVersion()
).toFixed(2);
const appUpdatedVersion = parseFloat(app_info.min_version).toFixed(2);
setLoadingAppInfo(false);
// console.log("appCurrentVersion =", parseFloat(appCurrentVersion));
// console.log("appUpdatedVersion =", parseFloat(appUpdatedVersion));
if (parseFloat(appCurrentVersion) < parseFloat(appUpdatedVersion)) {
// console.log("Inside if");
handleShowAppVersionUpdateModal();
}
}
})
.catch((e) => {
console.log("ERROR in appInfoFromServer ", JSON.stringify(e));
setLoadingAppInfo(false);
setAppUpdatedInfo(null);
});
}
async function fetchAllNotificationsPages() {
const all = [];
let lastKeyParam = null;
for (;;) {
const res = await notificationServices.getAllNotifications(lastKeyParam);
if (res.data?.status !== "success") break;
const list = res.data?.data?.notifications ?? [];
all.push(...list);
const lastKeyVal = res.data?.data?.lastkey;
if (!lastKeyVal) break;
lastKeyParam = lastKeyVal;
}
return all;
}
async function loadUnreadOverlayNotifications() {
try {
const list = await fetchAllNotificationsPages();
const overlays = list.filter(
(n) => n?.notification_type === "overlay" && !n?.is_read
// (n) => n?.notification_type === "overlay"
);
console.log('overlays - ',overlays)
setOverlayNotificationQueue(overlays);
} catch (e) {
console.log("Error in loadUnreadOverlayNotifications = ", e);
setOverlayNotificationQueue([]);
}
}
const handleCloseOverlayNotificationModal = () => {
setOverlayNotificationQueue((prev) => prev.slice(1));
};
async function getDashboardWallBanners() {
// console.log("Inside Dashboard: getDashboardWallBanners()...");
dashboardService
.getDashboardWallBanners()
.then((res) => {
console.log("getDashboardWallBanners RES = ", res.data);
if (res.data.status === "success") {
// console.log(
// "Success in getDashboardWallBanners =",
// res.data.data.items
// );
let allBannerItems = res.data?.data?.items;
let mainBanners =
allBannerItems.length > 0
? allBannerItems.filter((item) => item.position === "default")
: [];
let otherBanners =
allBannerItems.length > 0
? allBannerItems.filter(
(item) =>
item.position !== "default" && item.position !== "popup"
)
: [];
let popupBanners =
allBannerItems.length > 0
? allBannerItems.filter((item) => item.position === "popup")
: [];
// console.log("mainBanners = ", mainBanners);
// console.log("otherBanners = ", otherBanners);
// console.log("popupBanners = ", popupBanners);
setWallBanners(mainBanners);
setOtherBanners(otherBanners);
setPopupBanners(popupBanners);
setLoadingBanner(false);
}
})
.catch((error) => {
setLoadingBanner(false);
setWallBanners([]);
setOtherBanners([]);
setPopupBanners([]);
console.log("Error in getDashboardWallBanners = ", error);
});
}
useEffect(() => {
// console.log("DASHBOARD useeffect");
getDashboardWallBanners();
//Calling getNotificationStats for latest status..
getNotificationStats();
loadUnreadOverlayNotifications();
// const showPopup = sessionStorage.getItem("showPopup");
// console.log("showPopup --- ", showPopup);
// if (!showPopup) {
// console.log("inside if (!showPopup)");
// if (popupBanners.length > 0) {
// console.log("inside if (popupBanners.length > 0)");
// setTimeout(() => {
// handleShowDashboardAdvertisementModal();
// sessionStorage.setItem("showPopup", true);
// }, 500);
// }
// }
appInfoFromServer({
platform: authService.getDevicePlatform(),
package_name: authService.getAppID(),
});
}, []);
const currentOverlayNotification = overlayNotificationQueue[0] ?? null;
useEffect(() => {
if (!currentOverlayNotification?.id) return;
notificationServices
.markReadNotification({ id: currentOverlayNotification.id })
.then((res) => {
if (res.data?.status === "success") {
getNotificationStats();
}
})
.catch((err) =>
console.log("Error marking overlay notification read = ", err)
);
}, [currentOverlayNotification?.id]);
useEffect(() => {
const showPopup = sessionStorage.getItem("showPopup");
// console.log("showPopup = ", showPopup);
if (!showPopup) {
if (popupBanners.length > 0) {
// console.log("popupBanners.length = ", popupBanners.length);
setTimeout(() => {
handleShowDashboardAdvertisementModal();
sessionStorage.setItem("showPopup", true);
}, 500);
}
}
}, [popupBanners]);
// useEffect(() => {
// console.log("### appStateChange listener useEffect");
// console.log("## location.pathname = ", location.pathname);
// // Listen for app resume
// const listener = CapacitorApp.addListener(
// "appStateChange",
// ({ isActive }) => {
// console.log("App state -- isActive -- ", isActive);
// const isOnDashboard = location.pathname === "/dashboard";
// console.log("location.pathname = ", location.pathname);
// if (isActive && isOnDashboard) {
// console.log("Inside if (isActive && isOnDashboard)");
// console.log("App resumed and on Dashboard. Refetching...");
// /** Note:
// * Don't use window.location.reload() on every app state change or page navigation — it's heavy and bypasses SPA benefits.
// * When Should You Use window.location.reload()?
// - After logout, to clear all component state and start fresh.
// - After major app updates (e.g., language change, user role change).
// - After token refresh fails, and you want to force re-init.
// */
// // window.location.reload();
// getDashboardWallBanners();
// }
// }
// );
// // Clean up listener on unmount
// return () => {
// listener.remove();
// };
// }, [location.pathname]);
const swiperParams = {
shouldSwiperUpdate: true,
rebuildOnUpdate: true,
// autoHeight: true,
effect: "slide",
// autoplay: {
// delay: 4000,
// disableOnInteraction: false,
// },
pagination: {
el: ".swiper-pagination",
clickable: true,
},
spaceBetween: 15,
grabCursor: true,
};
return (
<PageComponent className="dashboard-content-wrapper">
<Container className="mb-2 banner-container bg-primary-lighter">
<Row className="row-cols-2 gx-2 mb-1 justify-content-center px-4">
<Col>
<Card
className="card-theme border-0 shadow-sm h-100"
style={{ background: `var(--color-kudos-light)` }}
>
<Link to="/appreciations">
<Card.Body className="p-2 text-center d-flex align-items-center">
<div
className="pe-none icon-wrap wrap-sm"
style={{ background: `var(--color-kudos)` }}
>
<img
src={`/img/appreciations-icon.png`}
alt="Appreciations Icon"
/>
</div>
<span className="d-block font-12 ms-2 text-truncate">
Appreciations
</span>
</Card.Body>
</Link>
</Card>
</Col>
<Col>
<Card
className="card-theme border-0 shadow-sm h-100"
style={{ background: `var(--color-badges-light)` }}
>
<Link to="/badges">
<Card.Body className="p-2 text-center d-flex align-items-center">
<div
className="pe-none icon-wrap wrap-sm"
style={{ background: `var(--color-badges)` }}
>
<img src={`/img/badges-icon.png`} alt="Badges Icon" />
</div>
<span className="d-block font-12 ms-2">Badges</span>
</Card.Body>
</Link>
</Card>
</Col>
{/* <Col>
<Card
className="card-theme border-0 shadow-sm h-100"
style={{ background: `var(--color-rewards-light)` }}
>
<Link to="/rewards">
<Card.Body className="p-2 text-center d-flex align-items-center">
<div
className="pe-none icon-wrap wrap-sm"
style={{ background: `var(--color-rewards)` }}
>
<img src={`/img/rewards-icon.png`} alt="Rewards Icon" />
</div>
<span className="d-block font-12 ms-2">Rewards</span>
</Card.Body>
</Link>
</Card>
</Col> */}
</Row>
<section
className={`${wallBanners.length > 0 ? "py-1 pb-3 py-sm-3" : ""}`}
>
{loadingBanner && <PlaceholderCard type="banners" />}
{!loadingBanner && wallBanners.length > 0 && (
<DashboardBanner
loading={loadingBanner}
banners={wallBanners}
itemClassName="rounded-1 shadow-none"
className=""
/>
)}
</section>
</Container>
<PerformanceStatsContainer />
{otherBanners?.length > 0 && (
<section
className={`overflow-hidden ${
otherBanners.length > 0
? "py-3 px-4 py-sm-3 my-2 bg-red-lighter1"
: "d-none"
}`}
>
{loadingBanner && <PlaceholderCard type="banners" />}
{!loadingBanner && otherBanners.length > 0 && (
<DashboardBanner
loading={loadingBanner}
banners={otherBanners}
itemClassName="rounded-4 shadow-sm cta-slide"
/>
)}
</section>
)}
<DashboardCampaignsContainer />
<DashboardCompetitionContestsContainer />
<DashboardMagazinesContainer />
{/* <section
className={`overflow-hidden ${
wallBanners.length > 0 ? "py-4 px-4 py-sm-3 bg-gray-lighter2" : ""
}`}
>
{loadingBanner && <PlaceholderCard type="banners" />}
{!loadingBanner && wallBanners.length > 0 && (
<DashboardBanner
loading={loadingBanner}
banners={wallBanners}
itemClassName="rounded-4 shadow-sm cta-slide"
className=""
/>
)}
</section> */}
<DashboardContestsContainer />
{/* <Button
type="button"
className="btn-theme btn-icon btn-lg btn-secondary btn-quick-action position-fixed border-0 rounded-circle shadow"
style={{ bottom: 120, right: 10 }}
onClick={() => {
navigate("/quick-actions");
}}
>
<CustomIcon tag="add3" className="font-32" />
</Button> */}
<DashboardAdvertiseModal
show={showDashboardAdvertisementModal}
loading={loadingBanner}
banners={popupBanners}
handleClose={handleCloseDashboardAdvertisementModal}
/>
<AppVersionUpdateModal
show={showAppVersionUpdateModal}
loading={loadingAppInfo}
handleClose={handleCloseAppVersionUpdateModal}
platform={authService.getDevicePlatform()}
appUpdatedInfo={appUpdatedInfo}
/>
<OverlayNotificationModal
show={Boolean(currentOverlayNotification)}
handleClose={handleCloseOverlayNotificationModal}
data={currentOverlayNotification}
/>
<div className="d-block" style={{ height: 150 }}></div>
</PageComponent>
);
}
export default Dashboard;