feat: Add Landing Page CMS, enhance Navbar with Solutions dropdown, mobile sticky footer, and optimize homepage features visibility
This commit is contained in:
parent
32cc257c87
commit
85bc3359d7
|
|
@ -17,7 +17,7 @@
|
||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
</url> -->
|
</url> -->
|
||||||
<url>
|
<url>
|
||||||
<loc>https://www.pozo.app/pricing-pozoapp</loc>
|
<loc>https://www.pozo.app/pricing</loc>
|
||||||
<lastmod>2025-10-13</lastmod>
|
<lastmod>2025-10-13</lastmod>
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
ENV_BASE_URL='/'
|
ENV_BASE_URL='/'
|
||||||
ENV_API_URL='http://192.168.1.37:8013'
|
# ENV_API_URL='http://192.168.1.37:8013'
|
||||||
ENV_API_URL_TOKEN='http://192.168.1.37:8001'
|
# ENV_API_URL_TOKEN='http://192.168.1.37:8001'
|
||||||
# ENV_API_URL_TOKEN='https://www.pozo.dev/JwtToken'
|
ENV_API_URL_TOKEN='https://www.pozo.dev/JwtToken'
|
||||||
# ENV_API_URL='https://www.pozo.dev/pozo-common-api'
|
ENV_API_URL='https://www.pozo.dev/pozo-common-api'
|
||||||
# ENV_IMAGE_UPLOAD_API_URL="https://api.pozo.app/pozo-common-image-api/"
|
# ENV_IMAGE_UPLOAD_API_URL="https://api.pozo.app/pozo-common-image-api/"
|
||||||
ENV_API_URL_RETAIL='http://192.168.1.37:8012/'
|
ENV_API_URL_RETAIL='http://192.168.1.37:8012/'
|
||||||
# ENV_API_URL_TOKEN='https://api.pozo.app/JwtToken'
|
# ENV_API_URL_TOKEN='https://api.pozo.app/JwtToken'
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,6 @@
|
||||||
#221 server
|
|
||||||
|
|
||||||
# ENV_BASE_URL='/home/'
|
|
||||||
# ENV_API_URL='http://api.pozo.co.in/Pozocommonapi_UnderTest'
|
|
||||||
# # ENV_API_URL='http://api.pozo.co.in/Pozocommonapi'
|
|
||||||
# ENV_IMAGE_UPLOAD_API_URL="https://api.pozo.app/pozo-common-image-api"
|
|
||||||
# ENV_SECRET_KEY="3a939a2eed2cca4b64cd47f51b23b135b2b9b765273f695d47682ea803c8429d"
|
|
||||||
# ENV_URL_SECRET_KEY="f2ef79b8b2d4fc1cc569726a5a753552257b4ff2872d6a71cf3119bce3f07c1b"
|
|
||||||
# ENV_MAIN_BASE_URL='http://pozo.co.in/'
|
|
||||||
# ENV_MAIN_REDIRECT_URL='/apps/retail/app-page/home'
|
|
||||||
|
|
||||||
# live server(#173 server)
|
|
||||||
# ENV_BASE_URL='/home/'
|
|
||||||
# ENV_API_URL_TOKEN='https://api.pozo.app/JwtToken'
|
|
||||||
# ENV_API_URL='https://api.pozo.app/pozo-common-api'
|
|
||||||
# ENV_IMAGE_UPLOAD_API_URL="https://api.pozo.app/pozo-common-image-api"
|
|
||||||
# ENV_SECRET_KEY="3a939a2eed2cca4b64cd47f51b23b135b2b9b765273f695d47682ea803c8429d"
|
|
||||||
# ENV_URL_SECRET_KEY="f2ef79b8b2d4fc1cc569726a5a753552257b4ff2872d6a71cf3119bce3f07c1b"
|
|
||||||
# ENV_MAIN_BASE_URL='https://www.pozo.app'
|
|
||||||
# ENV_MAIN_REDIRECT_URL='/apps/retail/app-page/home'
|
|
||||||
# ENV_PAYMENT_URL='https://pozo.app/paymentgateway/PozoPaymentGateway'
|
|
||||||
# ENV_CUSTOM_PAYMENT_URL='https://pozo.app/CustomPaymentGateway/CustomPaymentGateway'
|
|
||||||
# ENV_EMAIL_API='https://api.pozo.app/pozo-sms-email-template-api'
|
|
||||||
# ENV_API_URL_RETAIL='https://api.pozo.app/pozo-retail-api'
|
|
||||||
|
|
||||||
#172 server
|
#172 server
|
||||||
|
|
||||||
ENV_BASE_URL='/home/'
|
ENV_BASE_URL='/'
|
||||||
ENV_API_URL_TOKEN='https://www.pozo.dev/JwtToken'
|
ENV_API_URL_TOKEN='https://www.pozo.dev/JwtToken'
|
||||||
ENV_API_URL='https://www.pozo.dev/pozo-common-api'
|
ENV_API_URL='https://www.pozo.dev/pozo-common-api'
|
||||||
ENV_API_URL_RETAIL='https://www.pozo.dev/pozo-retail-api'
|
ENV_API_URL_RETAIL='https://www.pozo.dev/pozo-retail-api'
|
||||||
|
|
@ -37,5 +12,3 @@ ENV_MAIN_REDIRECT_URL='/apps/retail/app-page/home'
|
||||||
ENV_PAYMENT_URL='https://pozo.app/paymentgateway/PozoPaymentGateway'
|
ENV_PAYMENT_URL='https://pozo.app/paymentgateway/PozoPaymentGateway'
|
||||||
ENV_CUSTOM_PAYMENT_URL='https://pozo.app/CustomPaymentGateway/CustomPaymentGateway'
|
ENV_CUSTOM_PAYMENT_URL='https://pozo.app/CustomPaymentGateway/CustomPaymentGateway'
|
||||||
ENV_EMAIL_API='https://www.pozo.dev/pozo-sms-email-template-api'
|
ENV_EMAIL_API='https://www.pozo.dev/pozo-sms-email-template-api'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -811,3 +811,23 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.filterAssDcc {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
button {
|
||||||
|
width: max-content;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border: none;
|
||||||
|
font-family: "Poppins", sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
background-color: #e0ecff;
|
||||||
|
color: #1e6ae4;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
23
src/App.jsx
23
src/App.jsx
|
|
@ -69,6 +69,7 @@ import { useEffect } from "react";
|
||||||
import { checkSession, GenerateLogout } from "./features/signInPage/signInPage.js";
|
import { checkSession, GenerateLogout } from "./features/signInPage/signInPage.js";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { clearSession, getSession } from "./Services/others.js";
|
import { clearSession, getSession } from "./Services/others.js";
|
||||||
|
import { PostToken } from "./features/publicHome/publicHome.js";
|
||||||
import LoyaltysettingList from "./Pages/LoyaltySetting/LoyaltysettingList.jsx"
|
import LoyaltysettingList from "./Pages/LoyaltySetting/LoyaltysettingList.jsx"
|
||||||
import LoyaltysettingsForm from "./Pages/LoyaltySetting/LoyaltysettingsForm.jsx"
|
import LoyaltysettingsForm from "./Pages/LoyaltySetting/LoyaltysettingsForm.jsx"
|
||||||
import ActivationkeyGeneration from "./Pages/ActivationkeyGeneration/ActivationkeyGeneration.jsx";
|
import ActivationkeyGeneration from "./Pages/ActivationkeyGeneration/ActivationkeyGeneration.jsx";
|
||||||
|
|
@ -128,10 +129,28 @@ const App = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
// 🔑 Global token generation for direct URL access
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
sessionCheckFun()
|
const ensureToken = async () => {
|
||||||
|
const existingToken = sessionStorage.getItem("auth");
|
||||||
|
|
||||||
|
if (!existingToken) {
|
||||||
|
try {
|
||||||
|
console.log("🔑 App: Generating global auth token...");
|
||||||
|
await dispatch(PostToken({
|
||||||
|
username: "1000000001",
|
||||||
|
password: "1234"
|
||||||
|
})).unwrap();
|
||||||
|
console.log("✅ App: Token generated successfully");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ App: Token generation failed:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}, [navigate]);
|
ensureToken();
|
||||||
|
sessionCheckFun();
|
||||||
|
}, [navigate, dispatch]);
|
||||||
|
|
||||||
const sessionCheckFun=async()=>{
|
const sessionCheckFun=async()=>{
|
||||||
const UserId = getSession('UserId')
|
const UserId = getSession('UserId')
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,271 @@
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import "./LandingPageCMS.scss";
|
||||||
|
import {
|
||||||
|
FaHome,
|
||||||
|
FaHeading,
|
||||||
|
FaImage,
|
||||||
|
FaQuestionCircle,
|
||||||
|
FaArrowLeft,
|
||||||
|
FaSave,
|
||||||
|
FaEye,
|
||||||
|
FaLock,
|
||||||
|
FaMoon,
|
||||||
|
FaSun,
|
||||||
|
FaBars,
|
||||||
|
FaTimes
|
||||||
|
} from "react-icons/fa";
|
||||||
|
import { MdDashboard, MdEdit } from "react-icons/md";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
import { message } from "antd";
|
||||||
|
import { getAdminPanel, postAdminPanel, putAdminPanel } from "../features/AdminPanel/AdminPanel";
|
||||||
|
import { getSession } from "../Services/others";
|
||||||
|
|
||||||
|
// Section Components
|
||||||
|
import HeroContentEditor from "./Sections/HeroContentEditor";
|
||||||
|
import OfferingsEditor from "./Sections/OfferingsEditor";
|
||||||
|
import FeaturesEditor from "./Sections/FeaturesEditor";
|
||||||
|
import FAQEditor from "./Sections/FAQEditor";
|
||||||
|
|
||||||
|
const subDirectory = import.meta.env.ENV_BASE_URL;
|
||||||
|
|
||||||
|
const LandingPageCMS = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [activeSection, setActiveSection] = useState("hero");
|
||||||
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
|
const [hasChanges, setHasChanges] = useState(false);
|
||||||
|
const [isAuthorized, setIsAuthorized] = useState(false);
|
||||||
|
const [isCheckingAuth, setIsCheckingAuth] = useState(true);
|
||||||
|
const [isDarkMode, setIsDarkMode] = useState(true);
|
||||||
|
const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false);
|
||||||
|
|
||||||
|
// Load theme preference from localStorage
|
||||||
|
useEffect(() => {
|
||||||
|
const savedTheme = localStorage.getItem("landing-cms-theme");
|
||||||
|
if (savedTheme) {
|
||||||
|
setIsDarkMode(savedTheme === "dark");
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const toggleTheme = () => {
|
||||||
|
const newTheme = !isDarkMode;
|
||||||
|
setIsDarkMode(newTheme);
|
||||||
|
localStorage.setItem("landing-cms-theme", newTheme ? "dark" : "light");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 📱 Prevent body scroll when mobile sidebar is open
|
||||||
|
useEffect(() => {
|
||||||
|
if (isMobileSidebarOpen && window.innerWidth <= 900) {
|
||||||
|
document.body.style.overflow = "hidden";
|
||||||
|
} else {
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
document.body.style.overflow = "";
|
||||||
|
};
|
||||||
|
}, [isMobileSidebarOpen]);
|
||||||
|
|
||||||
|
// 🔒 Authentication Check
|
||||||
|
useEffect(() => {
|
||||||
|
const checkAuthentication = () => {
|
||||||
|
const userType = getSession("UserType");
|
||||||
|
const userId = getSession("UserId");
|
||||||
|
const authToken = sessionStorage.getItem("auth");
|
||||||
|
|
||||||
|
// Allow only Marketing, Super Admin, or Admin
|
||||||
|
const allowedUserTypes = ["Marketing", "Super Admin", "Admin", "Super Admin User"];
|
||||||
|
|
||||||
|
if (!authToken || !userId || !allowedUserTypes.includes(userType)) {
|
||||||
|
message.error("Unauthorized access! Please login first.");
|
||||||
|
navigate(`${subDirectory}signin`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsAuthorized(true);
|
||||||
|
setIsCheckingAuth(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
checkAuthentication();
|
||||||
|
}, [navigate]);
|
||||||
|
|
||||||
|
const sections = [
|
||||||
|
{
|
||||||
|
id: "hero",
|
||||||
|
name: "Hero Section",
|
||||||
|
icon: <FaHeading />,
|
||||||
|
description: "Main headline, subtext, and CTA button",
|
||||||
|
component: HeroContentEditor
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "offerings",
|
||||||
|
name: "Offerings",
|
||||||
|
icon: <FaImage />,
|
||||||
|
description: "3 key features (Experience, Innovation, Cost)",
|
||||||
|
component: OfferingsEditor
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "features",
|
||||||
|
name: "Features",
|
||||||
|
icon: <MdDashboard />,
|
||||||
|
description: "Product features and benefits",
|
||||||
|
component: FeaturesEditor
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "faq",
|
||||||
|
name: "FAQ Section",
|
||||||
|
icon: <FaQuestionCircle />,
|
||||||
|
description: "Frequently asked questions",
|
||||||
|
component: FAQEditor
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const currentSection = sections.find(s => s.id === activeSection);
|
||||||
|
const CurrentComponent = currentSection?.component;
|
||||||
|
|
||||||
|
const handlePreview = () => {
|
||||||
|
window.open(`${subDirectory}`, '_blank');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveAll = async () => {
|
||||||
|
setIsSaving(true);
|
||||||
|
try {
|
||||||
|
// Save logic will be implemented in each section component
|
||||||
|
message.success("All changes saved successfully!");
|
||||||
|
setHasChanges(false);
|
||||||
|
} catch (error) {
|
||||||
|
message.error("Failed to save changes");
|
||||||
|
} finally {
|
||||||
|
setIsSaving(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Show loading while checking auth
|
||||||
|
if (isCheckingAuth) {
|
||||||
|
return (
|
||||||
|
<div className="landing-cms-auth-loading">
|
||||||
|
<div className="auth-loading-spinner"></div>
|
||||||
|
<p>Verifying access...</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't render if not authorized (will redirect)
|
||||||
|
if (!isAuthorized) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`landing-cms-container ${isDarkMode ? 'dark-mode' : 'light-mode'}`}>
|
||||||
|
{/* Top Header */}
|
||||||
|
<div className="landing-cms-header">
|
||||||
|
<div className="landing-cms-header-left">
|
||||||
|
<button
|
||||||
|
className="landing-cms-mobile-menu-btn"
|
||||||
|
onClick={() => setIsMobileSidebarOpen(!isMobileSidebarOpen)}
|
||||||
|
aria-label="Toggle mobile menu"
|
||||||
|
>
|
||||||
|
{isMobileSidebarOpen ? <FaTimes /> : <FaBars />}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="landing-cms-back-btn"
|
||||||
|
onClick={() => navigate(`${subDirectory}`)}
|
||||||
|
>
|
||||||
|
<FaArrowLeft /> <span>Back to Home</span>
|
||||||
|
</button>
|
||||||
|
<div className="landing-cms-title-section">
|
||||||
|
<h1>Landing Page CMS</h1>
|
||||||
|
<p>Manage your homepage content dynamically</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="landing-cms-header-right">
|
||||||
|
<button
|
||||||
|
className="landing-cms-theme-toggle"
|
||||||
|
onClick={toggleTheme}
|
||||||
|
aria-label={isDarkMode ? "Switch to Light Mode" : "Switch to Dark Mode"}
|
||||||
|
title={isDarkMode ? "Switch to Light Mode" : "Switch to Dark Mode"}
|
||||||
|
>
|
||||||
|
{isDarkMode ? <FaSun /> : <FaMoon />}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="landing-cms-preview-btn"
|
||||||
|
onClick={handlePreview}
|
||||||
|
>
|
||||||
|
<FaEye /> <span>Preview</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`landing-cms-save-btn ${hasChanges ? 'has-changes' : ''}`}
|
||||||
|
onClick={handleSaveAll}
|
||||||
|
disabled={isSaving || !hasChanges}
|
||||||
|
>
|
||||||
|
<FaSave /> <span>{isSaving ? 'Saving...' : 'Save All Changes'}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="landing-cms-main">
|
||||||
|
{/* Mobile Overlay */}
|
||||||
|
{isMobileSidebarOpen && (
|
||||||
|
<div
|
||||||
|
className="landing-cms-mobile-overlay"
|
||||||
|
onClick={() => setIsMobileSidebarOpen(false)}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Sidebar Navigation */}
|
||||||
|
<div className={`landing-cms-sidebar ${isMobileSidebarOpen ? 'mobile-open' : ''}`}>
|
||||||
|
<div className="landing-cms-sidebar-header">
|
||||||
|
<FaHome />
|
||||||
|
<span>Content Sections</span>
|
||||||
|
</div>
|
||||||
|
<div className="landing-cms-nav-items">
|
||||||
|
{sections.map((section) => (
|
||||||
|
<button
|
||||||
|
key={section.id}
|
||||||
|
className={`landing-cms-nav-item ${activeSection === section.id ? 'active' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setActiveSection(section.id);
|
||||||
|
setIsMobileSidebarOpen(false); // Close on mobile after selection
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="landing-cms-nav-icon">{section.icon}</div>
|
||||||
|
<div className="landing-cms-nav-content">
|
||||||
|
<div className="landing-cms-nav-title">{section.name}</div>
|
||||||
|
<div className="landing-cms-nav-desc">{section.description}</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content Area */}
|
||||||
|
<div className="landing-cms-content">
|
||||||
|
<div className="landing-cms-content-header">
|
||||||
|
<div className="landing-cms-breadcrumb">
|
||||||
|
<span>Landing Page</span>
|
||||||
|
<span>/</span>
|
||||||
|
<span>{currentSection?.name}</span>
|
||||||
|
</div>
|
||||||
|
{hasChanges && (
|
||||||
|
<div className="landing-cms-unsaved-badge">
|
||||||
|
Unsaved changes
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="landing-cms-content-body">
|
||||||
|
{CurrentComponent && (
|
||||||
|
<CurrentComponent
|
||||||
|
onDataChange={() => setHasChanges(true)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LandingPageCMS;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,627 @@
|
||||||
|
// 🎨 Landing Page CMS - Clean Minimal Design
|
||||||
|
|
||||||
|
.landing-cms-container {
|
||||||
|
min-height: 100vh;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||||
|
transition: background 0.3s ease;
|
||||||
|
|
||||||
|
// Dark Mode
|
||||||
|
&.dark-mode {
|
||||||
|
background: #000;
|
||||||
|
color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Light Mode
|
||||||
|
&.light-mode {
|
||||||
|
background: #fafafa;
|
||||||
|
color: #171717;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auth Loading
|
||||||
|
.landing-cms-auth-loading {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #000;
|
||||||
|
|
||||||
|
.auth-loading-spinner {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 2px solid #333;
|
||||||
|
border-top-color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 0.6s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 1rem;
|
||||||
|
color: #888;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header
|
||||||
|
.landing-cms-header {
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1002;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
background: #111;
|
||||||
|
border-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
background: #fff;
|
||||||
|
border-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 0.875rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-header-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-mobile-menu-btn {
|
||||||
|
display: none;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
font-size: 18px;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
border-color: #333;
|
||||||
|
color: #e5e5e5;
|
||||||
|
|
||||||
|
&:hover, &:active {
|
||||||
|
border-color: #0ea5e9;
|
||||||
|
background: #1a1a1a;
|
||||||
|
color: #0ea5e9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
border-color: #d4d4d4;
|
||||||
|
color: #171717;
|
||||||
|
|
||||||
|
&:hover, &:active {
|
||||||
|
border-color: #0969da;
|
||||||
|
background: #f5f5f5;
|
||||||
|
color: #0969da;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-back-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
font-family: inherit;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
border-color: #333;
|
||||||
|
color: #e5e5e5;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #666;
|
||||||
|
background: #1a1a1a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
border-color: #d4d4d4;
|
||||||
|
color: #171717;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #999;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-title-section h1 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-title-section p {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-header-right {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-theme-toggle {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
font-size: 18px;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
border-color: #333;
|
||||||
|
color: #fbbf24;
|
||||||
|
|
||||||
|
&:hover, &:active {
|
||||||
|
border-color: #fbbf24;
|
||||||
|
background: #1a1a1a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
border-color: #d4d4d4;
|
||||||
|
color: #f59e0b;
|
||||||
|
|
||||||
|
&:hover, &:active {
|
||||||
|
border-color: #f59e0b;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-preview-btn,
|
||||||
|
.landing-cms-save-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.625rem 1.25rem;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
font-family: inherit;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 0.625rem 0.875rem;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-preview-btn {
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
border-color: #333;
|
||||||
|
color: #e5e5e5;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #666;
|
||||||
|
background: #1a1a1a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
border-color: #d4d4d4;
|
||||||
|
color: #171717;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #999;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-save-btn {
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
background: #fff;
|
||||||
|
color: #000;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.has-changes {
|
||||||
|
background: #10b981;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #059669;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
background: #000;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.has-changes {
|
||||||
|
background: #10b981;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #059669;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main
|
||||||
|
.landing-cms-main {
|
||||||
|
display: flex;
|
||||||
|
min-height: calc(100vh - 60px);
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sidebar
|
||||||
|
.landing-cms-sidebar {
|
||||||
|
width: 280px;
|
||||||
|
padding: 1.5rem 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
border-right: 1px solid;
|
||||||
|
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
background: #111;
|
||||||
|
border-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
background: #fff;
|
||||||
|
border-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
position: fixed !important;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1001 !important;
|
||||||
|
transform: translateX(-100%);
|
||||||
|
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.6);
|
||||||
|
padding-top: 70px;
|
||||||
|
width: 85%;
|
||||||
|
max-width: 320px;
|
||||||
|
|
||||||
|
&.mobile-open {
|
||||||
|
transform: translateX(0) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-sidebar-header {
|
||||||
|
padding: 0 1.25rem 1rem;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-nav-items {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.375rem;
|
||||||
|
padding: 0 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-nav-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 0.875rem 1rem;
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
text-align: left;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
padding: 1rem 1.25rem;
|
||||||
|
min-height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-nav-icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
font-size: 20px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
transition: color 0.2s;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-nav-content {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.landing-cms-nav-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
transition: color 0.2s;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #171717;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-nav-desc {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-mode &:hover {
|
||||||
|
background: #1a1a1a;
|
||||||
|
border-color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode &:hover {
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
.dark-mode & {
|
||||||
|
background: #1a1a1a;
|
||||||
|
border-color: #0ea5e9;
|
||||||
|
|
||||||
|
.landing-cms-nav-icon {
|
||||||
|
color: #10b981;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-nav-title {
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
background: #f0f9ff;
|
||||||
|
border-color: #0ea5e9;
|
||||||
|
|
||||||
|
.landing-cms-nav-icon {
|
||||||
|
color: #10b981;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-nav-title {
|
||||||
|
color: #000;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-nav-desc {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mobile Overlay
|
||||||
|
.landing-cms-mobile-overlay {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
display: block;
|
||||||
|
position: fixed !important;
|
||||||
|
inset: 0;
|
||||||
|
top: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.75);
|
||||||
|
z-index: 1000 !important;
|
||||||
|
animation: fadeIn 0.25s ease;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Content
|
||||||
|
.landing-cms-content {
|
||||||
|
flex: 1;
|
||||||
|
padding: 2rem 2.5rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
padding: 1.5rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-content-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
|
.landing-cms-breadcrumb {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #888;
|
||||||
|
|
||||||
|
span:last-child {
|
||||||
|
color: #e5e5e5;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #999;
|
||||||
|
|
||||||
|
span:last-child {
|
||||||
|
color: #171717;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-unsaved-badge {
|
||||||
|
padding: 0.375rem 0.875rem;
|
||||||
|
background: #fbbf24;
|
||||||
|
color: #000;
|
||||||
|
border-radius: 16px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.landing-cms-content-body {
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 2.5rem;
|
||||||
|
border: 1px solid;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
background: #111;
|
||||||
|
border-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
background: #fff;
|
||||||
|
border-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import React from "react";
|
||||||
|
import "./SectionEditor.scss";
|
||||||
|
import { FaQuestionCircle } from "react-icons/fa";
|
||||||
|
|
||||||
|
const FAQEditor = ({ onDataChange }) => {
|
||||||
|
return (
|
||||||
|
<div className="section-editor">
|
||||||
|
<div className="section-editor-header">
|
||||||
|
<div className="section-editor-icon">
|
||||||
|
<FaQuestionCircle />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2>FAQ Section</h2>
|
||||||
|
<p>Manage frequently asked questions (Coming Soon)</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="info-box">
|
||||||
|
<strong>Coming Soon:</strong>
|
||||||
|
FAQ editor will allow you to add, edit, and organize frequently asked questions.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FAQEditor;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import React from "react";
|
||||||
|
import "./SectionEditor.scss";
|
||||||
|
import { MdDashboard } from "react-icons/md";
|
||||||
|
|
||||||
|
const FeaturesEditor = ({ onDataChange }) => {
|
||||||
|
return (
|
||||||
|
<div className="section-editor">
|
||||||
|
<div className="section-editor-header">
|
||||||
|
<div className="section-editor-icon">
|
||||||
|
<MdDashboard />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2>Features Section</h2>
|
||||||
|
<p>Manage product features and benefits (Coming Soon)</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="info-box">
|
||||||
|
<strong>Coming Soon:</strong>
|
||||||
|
Features editor will allow you to manage the product features section dynamically.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FeaturesEditor;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,216 @@
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
import { message } from "antd";
|
||||||
|
import { getAdminPanel, postAdminPanel, putAdminPanel } from "../../features/AdminPanel/AdminPanel";
|
||||||
|
import "./SectionEditor.scss";
|
||||||
|
import { FaRegLightbulb, FaSave } from "react-icons/fa";
|
||||||
|
import { MdTitle, MdDescription } from "react-icons/md";
|
||||||
|
|
||||||
|
const HeroContentEditor = ({ onDataChange }) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
|
|
||||||
|
// Form fields
|
||||||
|
const [mainHeadline, setMainHeadline] = useState("Retail ERP & POS built for Indian MSMEs — fast billing, smart inventory, GST-ready.");
|
||||||
|
const [description, setDescription] = useState("A SaaS platform that empowers Small and Medium Businesses by digitizing operations and reducing Total Cost of Ownership with minimal investment.");
|
||||||
|
const [ctaButtonText, setCtaButtonText] = useState("Experience Now");
|
||||||
|
const [ctaButtonLink, setCtaButtonLink] = useState("/signin");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchHeroData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchHeroData = async () => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const res = await dispatch(
|
||||||
|
getAdminPanel({ sectionName: "HeroSection" })
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
if (res?.data?.statusCode === 1 && res?.data?.data?.length > 0) {
|
||||||
|
const heroData = res.data.data[0];
|
||||||
|
if (heroData.Content) {
|
||||||
|
const content = JSON.parse(heroData.Content);
|
||||||
|
setMainHeadline(content.mainHeadline || mainHeadline);
|
||||||
|
setDescription(content.description || description);
|
||||||
|
setCtaButtonText(content.ctaButtonText || ctaButtonText);
|
||||||
|
setCtaButtonLink(content.ctaButtonLink || ctaButtonLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("No existing hero data, using defaults");
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
if (!mainHeadline.trim() || !description.trim()) {
|
||||||
|
message.error("Headline and description are required!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsSaving(true);
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
SectionName: "HeroSection",
|
||||||
|
Content: JSON.stringify({
|
||||||
|
mainHeadline: mainHeadline.trim(),
|
||||||
|
description: description.trim(),
|
||||||
|
ctaButtonText: ctaButtonText.trim(),
|
||||||
|
ctaButtonLink: ctaButtonLink.trim()
|
||||||
|
}),
|
||||||
|
ActiveStatus: "A",
|
||||||
|
CreatedBy: 1,
|
||||||
|
ModifiedBy: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
await dispatch(postAdminPanel(data)).unwrap();
|
||||||
|
message.success("Hero section saved successfully!");
|
||||||
|
onDataChange?.();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Save error:", error);
|
||||||
|
message.error("Failed to save. Please try again.");
|
||||||
|
} finally {
|
||||||
|
setIsSaving(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="section-editor-loading">
|
||||||
|
<div className="loading-spinner"></div>
|
||||||
|
<p>Loading hero section...</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="section-editor">
|
||||||
|
<div className="section-editor-header">
|
||||||
|
<div className="section-editor-icon">
|
||||||
|
<MdTitle />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2>Hero Section Content</h2>
|
||||||
|
<p>Manage the main headline, description, and CTA button on your landing page</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="section-editor-form">
|
||||||
|
{/* Main Headline */}
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="mainHeadline">
|
||||||
|
Main Headline
|
||||||
|
<span className="label-hint">First thing visitors see</span>
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
id="mainHeadline"
|
||||||
|
value={mainHeadline}
|
||||||
|
onChange={(e) => {
|
||||||
|
setMainHeadline(e.target.value);
|
||||||
|
onDataChange?.();
|
||||||
|
}}
|
||||||
|
placeholder="Enter main headline (press Enter for new line)"
|
||||||
|
rows={4}
|
||||||
|
className="form-textarea headline-input"
|
||||||
|
/>
|
||||||
|
<div className="input-help">
|
||||||
|
Tip: Press Enter to add line breaks
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Description */}
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="description">
|
||||||
|
Description
|
||||||
|
<span className="label-hint">Supporting text</span>
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
id="description"
|
||||||
|
value={description}
|
||||||
|
onChange={(e) => {
|
||||||
|
setDescription(e.target.value);
|
||||||
|
onDataChange?.();
|
||||||
|
}}
|
||||||
|
placeholder="Enter description"
|
||||||
|
rows={3}
|
||||||
|
className="form-textarea"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* CTA Button */}
|
||||||
|
<div className="form-row">
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="ctaButtonText">Button Text</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="ctaButtonText"
|
||||||
|
value={ctaButtonText}
|
||||||
|
onChange={(e) => {
|
||||||
|
setCtaButtonText(e.target.value);
|
||||||
|
onDataChange?.();
|
||||||
|
}}
|
||||||
|
placeholder="e.g., Get Started"
|
||||||
|
className="form-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="ctaButtonLink">Button Link</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="ctaButtonLink"
|
||||||
|
value={ctaButtonLink}
|
||||||
|
onChange={(e) => {
|
||||||
|
setCtaButtonLink(e.target.value);
|
||||||
|
onDataChange?.();
|
||||||
|
}}
|
||||||
|
placeholder="e.g., /signin"
|
||||||
|
className="form-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Single Combined Preview */}
|
||||||
|
<div className="form-group">
|
||||||
|
<label>Live Preview</label>
|
||||||
|
<div className="input-preview">
|
||||||
|
<div className="preview-text headline-preview">
|
||||||
|
{mainHeadline.split('\n').map((line, i) => (
|
||||||
|
<React.Fragment key={i}>
|
||||||
|
{line}
|
||||||
|
{i < mainHeadline.split('\n').length - 1 && <br />}
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="preview-text" style={{ marginTop: '1rem', fontSize: '14px', color: '#666' }}>
|
||||||
|
{description}
|
||||||
|
</div>
|
||||||
|
<div className="button-preview">
|
||||||
|
<button className="preview-cta-btn">
|
||||||
|
{ctaButtonText}
|
||||||
|
<div className="preview-icon">→</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Save Button */}
|
||||||
|
<div className="section-editor-actions">
|
||||||
|
<button
|
||||||
|
onClick={handleSave}
|
||||||
|
disabled={isSaving}
|
||||||
|
className="save-section-btn"
|
||||||
|
>
|
||||||
|
<FaSave /> {isSaving ? "Saving..." : "Save Changes"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HeroContentEditor;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,212 @@
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
import { message } from "antd";
|
||||||
|
import { getAdminPanel, postAdminPanel } from "../../features/AdminPanel/AdminPanel";
|
||||||
|
import "./SectionEditor.scss";
|
||||||
|
import { FaSave, FaLightbulb, FaCog, FaDollarSign } from "react-icons/fa";
|
||||||
|
import { MdStar } from "react-icons/md";
|
||||||
|
|
||||||
|
const OfferingsEditor = ({ onDataChange }) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
|
|
||||||
|
const defaultOfferings = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "Experience",
|
||||||
|
description: "Proven expertise delivering real value",
|
||||||
|
icon: "experience"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "Innovation",
|
||||||
|
description: "Smarter intelligence for better outcomes",
|
||||||
|
icon: "innovation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: "Cost Efficiency",
|
||||||
|
description: "Maximum value with minimal cost",
|
||||||
|
icon: "cost"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const [offerings, setOfferings] = useState(defaultOfferings);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchOfferingsData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchOfferingsData = async () => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const res = await dispatch(
|
||||||
|
getAdminPanel({ sectionName: "Offerings" })
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
if (res?.data?.statusCode === 1 && res?.data?.data?.length > 0) {
|
||||||
|
const offeringsData = res.data.data[0];
|
||||||
|
if (offeringsData.Content) {
|
||||||
|
const content = JSON.parse(offeringsData.Content);
|
||||||
|
setOfferings(content.offerings || defaultOfferings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("No existing offerings data, using defaults");
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOfferingChange = (id, field, value) => {
|
||||||
|
setOfferings(offerings.map(offering =>
|
||||||
|
offering.id === id ? { ...offering, [field]: value } : offering
|
||||||
|
));
|
||||||
|
onDataChange?.();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
// Validation
|
||||||
|
for (const offering of offerings) {
|
||||||
|
if (!offering.title.trim() || !offering.description.trim()) {
|
||||||
|
message.error(`Please fill all fields for ${offering.title || 'offering'}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsSaving(true);
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
SectionName: "Offerings",
|
||||||
|
Content: JSON.stringify({
|
||||||
|
offerings: offerings.map(o => ({
|
||||||
|
id: o.id,
|
||||||
|
title: o.title.trim(),
|
||||||
|
description: o.description.trim(),
|
||||||
|
icon: o.icon
|
||||||
|
}))
|
||||||
|
}),
|
||||||
|
ActiveStatus: "A",
|
||||||
|
CreatedBy: 1,
|
||||||
|
ModifiedBy: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
await dispatch(postAdminPanel(data)).unwrap();
|
||||||
|
message.success("Offerings saved successfully!");
|
||||||
|
onDataChange?.();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Save error:", error);
|
||||||
|
message.error("Failed to save. Please try again.");
|
||||||
|
} finally {
|
||||||
|
setIsSaving(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getIconComponent = (iconName) => {
|
||||||
|
switch(iconName) {
|
||||||
|
case "experience": return <MdStar />;
|
||||||
|
case "innovation": return <FaCog />;
|
||||||
|
case "cost": return <FaDollarSign />;
|
||||||
|
default: return <FaLightbulb />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="section-editor-loading">
|
||||||
|
<div className="loading-spinner"></div>
|
||||||
|
<p>Loading offerings...</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="section-editor">
|
||||||
|
<div className="section-editor-header">
|
||||||
|
<div className="section-editor-icon">
|
||||||
|
<FaLightbulb />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2>Offerings Section</h2>
|
||||||
|
<p>Manage the 3 key value propositions displayed on your landing page</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="info-box">
|
||||||
|
<strong>About Offerings:</strong>
|
||||||
|
These 3 features appear below the main headline showing your key value propositions:
|
||||||
|
Experience, Innovation, and Cost Efficiency.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="section-editor-form">
|
||||||
|
{offerings.map((offering, index) => (
|
||||||
|
<div key={offering.id} className="offering-card">
|
||||||
|
<div className="offering-card-header">
|
||||||
|
<div className="offering-icon-preview">
|
||||||
|
{getIconComponent(offering.icon)}
|
||||||
|
</div>
|
||||||
|
<h3>Offering {index + 1}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-row">
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor={`title-${offering.id}`}>Title</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id={`title-${offering.id}`}
|
||||||
|
value={offering.title}
|
||||||
|
onChange={(e) => handleOfferingChange(offering.id, 'title', e.target.value)}
|
||||||
|
placeholder="e.g., Experience, Innovation"
|
||||||
|
className="form-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor={`icon-${offering.id}`}>Icon Type</label>
|
||||||
|
<select
|
||||||
|
id={`icon-${offering.id}`}
|
||||||
|
value={offering.icon}
|
||||||
|
onChange={(e) => handleOfferingChange(offering.id, 'icon', e.target.value)}
|
||||||
|
className="form-input"
|
||||||
|
>
|
||||||
|
<option value="experience">Experience (Star)</option>
|
||||||
|
<option value="innovation">Innovation (Cog)</option>
|
||||||
|
<option value="cost">Cost (Dollar)</option>
|
||||||
|
<option value="lightbulb">Light Bulb</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor={`desc-${offering.id}`}>Description</label>
|
||||||
|
<textarea
|
||||||
|
id={`desc-${offering.id}`}
|
||||||
|
value={offering.description}
|
||||||
|
onChange={(e) => handleOfferingChange(offering.id, 'description', e.target.value)}
|
||||||
|
placeholder="Brief description of this offering"
|
||||||
|
rows={2}
|
||||||
|
className="form-textarea"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* Save Button */}
|
||||||
|
<div className="section-editor-actions">
|
||||||
|
<button
|
||||||
|
onClick={handleSave}
|
||||||
|
disabled={isSaving}
|
||||||
|
className="save-section-btn"
|
||||||
|
>
|
||||||
|
<FaSave /> {isSaving ? "Saving..." : "Save Offerings"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OfferingsEditor;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,494 @@
|
||||||
|
// Section Editor - Clean & Simple
|
||||||
|
|
||||||
|
.section-editor {
|
||||||
|
max-width: 720px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-editor-header {
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
|
||||||
|
.section-editor-icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 0 0 0.5rem 0;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 700;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-editor-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form Group
|
||||||
|
.form-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.625rem;
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #171717;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-hint {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 1.5rem;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
.form-input,
|
||||||
|
.form-textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.875rem 1rem;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: inherit;
|
||||||
|
transition: all 0.2s;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
background: #000;
|
||||||
|
border-color: #333;
|
||||||
|
color: #e5e5e5;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #0ea5e9;
|
||||||
|
background: #0a0a0a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
background: #fafafa;
|
||||||
|
border-color: #d4d4d4;
|
||||||
|
color: #000;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #0ea5e9;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
border-color: #ef4444 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-textarea {
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 100px;
|
||||||
|
line-height: 1.6;
|
||||||
|
|
||||||
|
&.headline-input {
|
||||||
|
font-size: 17px;
|
||||||
|
font-weight: 600;
|
||||||
|
min-height: 130px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Help
|
||||||
|
.input-help {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preview - Single Combined
|
||||||
|
.input-preview {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
padding: 2.5rem;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
background: #0a0a0a;
|
||||||
|
border-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
display: block;
|
||||||
|
font-size: 11px;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #0ea5e9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #0969da;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-text {
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.7;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #cbd5e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #475569;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.headline-preview {
|
||||||
|
font-size: 40px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.15;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-preview {
|
||||||
|
margin-top: 2rem;
|
||||||
|
|
||||||
|
.preview-cta-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
background: #10b981;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
font-family: inherit;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 0.875rem 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #059669;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
.section-editor-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding-top: 2rem;
|
||||||
|
border-top: 1px solid;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
border-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
border-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.save-section-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.625rem;
|
||||||
|
padding: 1rem 2.5rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
font-family: inherit;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
background: #0ea5e9;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: #0284c7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
background: #0969da;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: #0550ae;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loading
|
||||||
|
.section-editor-loading {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 450px;
|
||||||
|
|
||||||
|
.loading-spinner {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 2px solid;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 0.6s linear infinite;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
border-color: #333;
|
||||||
|
border-top-color: #0ea5e9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
border-color: #e5e5e5;
|
||||||
|
border-top-color: #0969da;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-size: 13px;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info Box
|
||||||
|
.info-box {
|
||||||
|
padding: 1.125rem 1.375rem;
|
||||||
|
border-left: 3px solid;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.6;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
background: rgba(14, 165, 233, 0.1);
|
||||||
|
border-color: #0ea5e9;
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
background: rgba(9, 105, 218, 0.05);
|
||||||
|
border-color: #0969da;
|
||||||
|
color: #475569;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #0ea5e9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #0969da;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Offering Cards
|
||||||
|
.offering-card {
|
||||||
|
padding: 1.75rem;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.2s;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
background: #0a0a0a;
|
||||||
|
border-color: #333;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #0ea5e9;
|
||||||
|
background: #0f0f0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
background: #fafafa;
|
||||||
|
border-color: #d4d4d4;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #0969da;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offering-card-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
|
||||||
|
.offering-icon-preview {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
background: #10b981;
|
||||||
|
border-radius: 6px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 22px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
.dark-mode & {
|
||||||
|
color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-mode & {
|
||||||
|
color: #171717;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select.form-input {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
@ -95,7 +95,6 @@ const ApplicationForm = ({ formType }) => {
|
||||||
postData["AppURLType"] = SelectedCategory == categoryData?.filter(item => item?.ConfigName == "Retail")[0]?.ConfigId ? 'I' : 'E';;
|
postData["AppURLType"] = SelectedCategory == categoryData?.filter(item => item?.ConfigName == "Retail")[0]?.ConfigId ? 'I' : 'E';;
|
||||||
postData["AppLogo"] = imageUrl;
|
postData["AppLogo"] = imageUrl;
|
||||||
postData["AppName"] = values.AppName;
|
postData["AppName"] = values.AppName;
|
||||||
postData["NavigationURL"] = values.NavigationURL;
|
|
||||||
postData["AppURL"] = SelectedCategory == categoryData?.filter(item => item?.ConfigName == "Retail")[0]?.ConfigId ? URLToggle ? homepageurl : values.AppURL : values.AppURL;
|
postData["AppURL"] = SelectedCategory == categoryData?.filter(item => item?.ConfigName == "Retail")[0]?.ConfigId ? URLToggle ? homepageurl : values.AppURL : values.AppURL;
|
||||||
postData["CateId"] = values.CateId;
|
postData["CateId"] = values.CateId;
|
||||||
postData["CreatedBy"] = getSession('UserId')
|
postData["CreatedBy"] = getSession('UserId')
|
||||||
|
|
@ -328,31 +327,7 @@ const ApplicationForm = ({ formType }) => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
name="NavigationURL"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
pattern: /^(?!\s*$).+/,
|
|
||||||
message: "Please Enter Navigation URL",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
validator: async (_, value) => {
|
|
||||||
await validateSafeInput(value);
|
|
||||||
return Promise.resolve();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]}>
|
|
||||||
<InputField
|
|
||||||
field="NavigationURL"
|
|
||||||
autoComplete="off"
|
|
||||||
label={<label className="required">Navigation URL</label>}
|
|
||||||
fieldState={true}
|
|
||||||
fieldApi={true}
|
|
||||||
isOnChange={formType == "edit" ? true : false}
|
|
||||||
defaultValue={editstate?.NavigationURL}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<div className="upload_btn">
|
<div className="upload_btn">
|
||||||
<p>Upload Logo</p>
|
<p>Upload Logo</p>
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,7 @@ const AllTemplates = () => {
|
||||||
{/* <nav 1 */}
|
{/* <nav 1 */}
|
||||||
|
|
||||||
{templateData?.Navbar?.[0] === "Navbar1" && (
|
{templateData?.Navbar?.[0] === "Navbar1" && (
|
||||||
<div className="applayout1" style={{ display: "flex", flexDirection: "row", columnGap: '2rem' ,flexDirection:"column"}}>
|
<div className="applayout1" style={{ display: "flex", flexDirection: "column", columnGap: '2rem' }}>
|
||||||
<div className="Appsidenav" >
|
<div className="Appsidenav" >
|
||||||
<div id="Navbar">
|
<div id="Navbar">
|
||||||
{templateData["Navbar"]?.[0] == "Navbar1" && (
|
{templateData["Navbar"]?.[0] == "Navbar1" && (
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState, lazy, Suspense, useCallback } from "react";
|
||||||
import { useLocation, useParams } from "react-router-dom";
|
import { useLocation, useParams } from "react-router-dom";
|
||||||
import { useSelector, useDispatch } from "react-redux";
|
import { useSelector, useDispatch } from "react-redux";
|
||||||
import { Skeleton } from "antd";
|
import { Skeleton } from "antd";
|
||||||
|
|
@ -9,42 +9,49 @@ import {
|
||||||
getTemplate,
|
getTemplate,
|
||||||
getTemplateData,
|
getTemplateData,
|
||||||
} from "../../features/themeChange/themeChange";
|
} from "../../features/themeChange/themeChange";
|
||||||
|
import { PostToken } from "../../features/publicHome/publicHome";
|
||||||
|
|
||||||
|
// ✅ Critical imports - Load immediately (above fold)
|
||||||
|
import HomeNav from "../publichome/PublicNavBar/NavBar";
|
||||||
import Navbar3 from "../themeTemplate/TemplateComps/NavBars/NavBars/NavBar3HorizontalPreview";
|
import Navbar3 from "../themeTemplate/TemplateComps/NavBars/NavBars/NavBar3HorizontalPreview";
|
||||||
import Navbar2 from "../themeTemplate/TemplateComps/NavBars/NavBars/NavBarHorizontalPreview";
|
import Navbar2 from "../themeTemplate/TemplateComps/NavBars/NavBars/NavBarHorizontalPreview";
|
||||||
import Navbar1 from "../themeTemplate/TemplateComps/NavBars/SideNav/SideNavBarPreview";
|
import Navbar1 from "../themeTemplate/TemplateComps/NavBars/SideNav/SideNavBarPreview";
|
||||||
import OverView1 from "../themeTemplate/TemplateComps/OverVIews/OverView1";
|
import OverView1 from "../themeTemplate/TemplateComps/OverVIews/OverView1";
|
||||||
import OverView2 from "../themeTemplate/TemplateComps/OverVIews/OverView2";
|
import OverView2 from "../themeTemplate/TemplateComps/OverVIews/OverView2";
|
||||||
import Features1 from "../themeTemplate/TemplateComps/Features/Features1";
|
import OverviewTemp3 from "./TemplateComps/OverVIews/OverViewTemplate3";
|
||||||
import Features2 from "../themeTemplate/TemplateComps/Features/Feature2";
|
import HeroSection from "./TemplateComps/OverVIews/OverView3";
|
||||||
import Pricing1 from "../themeTemplate/TemplateComps/Pricing/Pricing1";
|
import Loader from "../../Components/Loader/Loader";
|
||||||
import Pricing2 from "../themeTemplate/TemplateComps/Pricing/Pricing2";
|
|
||||||
import Pricing3 from "../themeTemplate/TemplateComps/Pricing/Pricing3";
|
|
||||||
|
|
||||||
import Faq1 from "../themeTemplate/TemplateComps/Faq/FaqPreview1";
|
// 🚀 Lazy imports - Below fold components
|
||||||
import Faq2 from "../themeTemplate/TemplateComps/Faq/FaqPreview2";
|
const Features1 = lazy(() => import("../themeTemplate/TemplateComps/Features/Features1"));
|
||||||
import DownloadSource from "../themeTemplate/TemplateComps/downloadsource/downloadSource";
|
const Features2 = lazy(() => import("../themeTemplate/TemplateComps/Features/Feature2"));
|
||||||
import Contact from "../themeTemplate/TemplateComps/contact/contact";
|
const Feature3 = lazy(() => import("./TemplateComps/Features/Feature3"));
|
||||||
import Footer1 from "../themeTemplate/TemplateComps/Footer/FooterTemplate1";
|
|
||||||
import Footer2 from "../themeTemplate/TemplateComps/Footer/FooterTemplate2";
|
const Pricing1 = lazy(() => import("../themeTemplate/TemplateComps/Pricing/Pricing1"));
|
||||||
import Footer3 from "../themeTemplate/TemplateComps/Footer/FooterTemplate3";
|
const Pricing2 = lazy(() => import("../themeTemplate/TemplateComps/Pricing/Pricing2"));
|
||||||
import HomeNav from "../publichome/PublicNavBar/NavBar";
|
const Pricing3 = lazy(() => import("../themeTemplate/TemplateComps/Pricing/Pricing3"));
|
||||||
|
|
||||||
|
const Faq1 = lazy(() => import("../themeTemplate/TemplateComps/Faq/FaqPreview1"));
|
||||||
|
const Faq2 = lazy(() => import("../themeTemplate/TemplateComps/Faq/FaqPreview2"));
|
||||||
|
const FaqTemplate3 = lazy(() => import("./TemplateComps/Faq/FaqTemplate3"));
|
||||||
|
const FAQSection = lazy(() => import("./TemplateComps/Faq/FaqPreview3"));
|
||||||
|
const CommonFaq = lazy(() => import("./TemplateComps/Faq/CommonFaq"));
|
||||||
|
|
||||||
|
const Footer1 = lazy(() => import("../themeTemplate/TemplateComps/Footer/FooterTemplate1"));
|
||||||
|
const Footer2 = lazy(() => import("../themeTemplate/TemplateComps/Footer/FooterTemplate2"));
|
||||||
|
const Footer3 = lazy(() => import("../themeTemplate/TemplateComps/Footer/FooterTemplate3"));
|
||||||
|
const FooterTemplate3 = lazy(() => import("../themeTemplate/TemplateComps/Footer/FooterTemplate3"));
|
||||||
|
|
||||||
|
const DownloadSource = lazy(() => import("../themeTemplate/TemplateComps/downloadsource/downloadSource"));
|
||||||
|
const Contact = lazy(() => import("../themeTemplate/TemplateComps/contact/contact"));
|
||||||
|
const CTAPreview = lazy(() => import("./TemplateComps/CTASection/CTASectionPreview"));
|
||||||
|
const ShowcasePreview = lazy(() => import("./TemplateComps/Showcase/showcasepreviw"));
|
||||||
|
const TestimonialTemplate = lazy(() => import("./TemplateComps/Testimonial/TestimonialTemplate"));
|
||||||
|
const TestimonialPreView = lazy(() => import("./TemplateComps/Testimonial/TestimonialPreView"));
|
||||||
|
|
||||||
import "../../styles/template/template/template.css";
|
import "../../styles/template/template/template.css";
|
||||||
import Feature3 from "./TemplateComps/Features/Feature3";
|
|
||||||
import { getSession } from "../../Services/others";
|
import { getSession } from "../../Services/others";
|
||||||
import OverviewTemp3 from "./TemplateComps/OverVIews/OverViewTemplate3";
|
|
||||||
import FaqTemplate3 from "./TemplateComps/Faq/FaqTemplate3";
|
|
||||||
import NavBar3HorizontalPreview from "../themeTemplate/TemplateComps/NavBars/NavBars/NavBar3HorizontalPreview";
|
|
||||||
import FooterTemplate3 from "../themeTemplate/TemplateComps/Footer/FooterTemplate3";
|
|
||||||
import CTAPreview from "./TemplateComps/CTASection/CTASectionPreview";
|
|
||||||
import ShowcasePreview from "./TemplateComps/Showcase/showcasepreviw";
|
|
||||||
import TestimonialTemplate from "./TemplateComps/Testimonial/TestimonialTemplate";
|
|
||||||
import { getCustomertestimonials } from "../../features/testimonials/testimonials";
|
import { getCustomertestimonials } from "../../features/testimonials/testimonials";
|
||||||
import HeroSection from "./TemplateComps/OverVIews/OverView3";
|
|
||||||
import FAQSection from "./TemplateComps/Faq/FaqPreview3";
|
|
||||||
import Loader from "../../Components/Loader/Loader";
|
|
||||||
import TestimonialPreView from "./TemplateComps/Testimonial/TestimonialPreView";
|
|
||||||
import CommonFaq from "./TemplateComps/Faq/CommonFaq";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { LuMousePointerClick } from "react-icons/lu";
|
import { LuMousePointerClick } from "react-icons/lu";
|
||||||
const subDirectory = import.meta.env.ENV_BASE_URL
|
const subDirectory = import.meta.env.ENV_BASE_URL
|
||||||
|
|
@ -62,11 +69,60 @@ const Template = () => {
|
||||||
|
|
||||||
const changeCurrentColorValues = useSelector(changeCurrentColorValue);
|
const changeCurrentColorValues = useSelector(changeCurrentColorValue);
|
||||||
console.log("templateData", templateData)
|
console.log("templateData", templateData)
|
||||||
|
|
||||||
|
// 🔑 Auto-generate token for direct URL access
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(getTemplate(params.appName)).unwrap();
|
const initializeAuth = async () => {
|
||||||
|
try {
|
||||||
|
// Check if token already exists
|
||||||
|
const existingToken = sessionStorage.getItem("auth");
|
||||||
|
|
||||||
|
if (!existingToken) {
|
||||||
|
console.log("🔑 Generating token for direct URL access...");
|
||||||
|
// Generate token
|
||||||
|
const tokenData = {
|
||||||
|
username: "1000000001",
|
||||||
|
password: "1234",
|
||||||
|
};
|
||||||
|
await dispatch(PostToken(tokenData)).unwrap();
|
||||||
|
console.log("✅ Token generated successfully");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert clean URL slug back to proper app name for API call
|
||||||
|
// URL: salon-spa-and-beauty-parlour → API: Salon, Spa and Beauty Parlour
|
||||||
|
// URL: beauty-and-cosmetics-shop → API: Beauty and Cosmetics Shop
|
||||||
|
const appNameForApi = params.appName
|
||||||
|
.split('-')
|
||||||
|
.map((word, index, arr) => {
|
||||||
|
// Keep 'and' lowercase unless it's the first word
|
||||||
|
if (word === 'and' && index > 0 && index < arr.length - 1) {
|
||||||
|
return 'and';
|
||||||
|
}
|
||||||
|
// Capitalize first letter
|
||||||
|
return word.charAt(0).toUpperCase() + word.slice(1);
|
||||||
|
})
|
||||||
|
.join(' ');
|
||||||
|
|
||||||
|
console.log("📦 URL slug:", params.appName);
|
||||||
|
console.log("📦 Loading template for:", appNameForApi);
|
||||||
|
|
||||||
|
// Fetch template data with proper app name
|
||||||
|
await dispatch(getTemplate(appNameForApi)).unwrap();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Error initializing template:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
initializeAuth();
|
||||||
|
}, [params.appName, dispatch]);
|
||||||
|
|
||||||
|
// Separate useEffect for scroll tracking with throttle
|
||||||
|
useEffect(() => {
|
||||||
|
let ticking = false;
|
||||||
|
|
||||||
const trackPosition = () => {
|
const trackPosition = () => {
|
||||||
const divElement = navbarRef?.current;
|
const divElement = navbarRef?.current;
|
||||||
if (!divElement) return; // Ensure divElement exists before proceeding
|
if (!divElement) return;
|
||||||
|
|
||||||
const { top } = divElement.getBoundingClientRect();
|
const { top } = divElement.getBoundingClientRect();
|
||||||
|
|
||||||
|
|
@ -75,12 +131,20 @@ const changeCurrentColorValues = useSelector(changeCurrentColorValue);
|
||||||
} else {
|
} else {
|
||||||
divElement.classList.remove("navBarHover");
|
divElement.classList.remove("navBarHover");
|
||||||
}
|
}
|
||||||
|
ticking = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener("scroll", trackPosition);
|
const handleScroll = () => {
|
||||||
|
if (!ticking) {
|
||||||
|
window.requestAnimationFrame(trackPosition);
|
||||||
|
ticking = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("scroll", handleScroll, { passive: true });
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener("scroll", trackPosition); // Pass the same event handler function here
|
window.removeEventListener("scroll", handleScroll);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
@ -108,16 +172,22 @@ const changeCurrentColorValues = useSelector(changeCurrentColorValue);
|
||||||
}, [location?.state]);
|
}, [location?.state]);
|
||||||
|
|
||||||
const [Testimonialsdata, setTestimonialsdata] = useState([]);
|
const [Testimonialsdata, setTestimonialsdata] = useState([]);
|
||||||
useEffect(() => {
|
|
||||||
apicall()
|
// 🚀 Memoized API call
|
||||||
}, [])
|
const apicall = useCallback(async () => {
|
||||||
|
try {
|
||||||
const apicall = async () => {
|
const res = await dispatch(getCustomertestimonials()).unwrap();
|
||||||
let res = await dispatch(getCustomertestimonials()).unwrap();
|
if (res?.data?.statusCode === 1) {
|
||||||
if (res?.data?.statusCode === 1) {
|
setTestimonialsdata(res?.data?.data);
|
||||||
setTestimonialsdata(res?.data?.data);
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching testimonials:", error);
|
||||||
}
|
}
|
||||||
}
|
}, [dispatch]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
apicall();
|
||||||
|
}, [apicall]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (location?.state?.scrollToId) {
|
if (location?.state?.scrollToId) {
|
||||||
scrollToSection(location.state.scrollToId);
|
scrollToSection(location.state.scrollToId);
|
||||||
|
|
@ -314,71 +384,72 @@ useEffect(() => {
|
||||||
<HeroSection data={templateData["Overview"][1]} />
|
<HeroSection data={templateData["Overview"][1]} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div id="ShowCase">
|
<Suspense fallback={null}>
|
||||||
{templateData["Showcase"]?.[0] == "Showcase1" && (
|
<div id="ShowCase">
|
||||||
<ShowcasePreview data={templateData["Showcase"][1]?.[0]?.FieldValue} key={"ShowCase"} />
|
{templateData["Showcase"]?.[0] == "Showcase1" && (
|
||||||
)}
|
<ShowcasePreview data={templateData["Showcase"][1]?.[0]?.FieldValue} key={"ShowCase"} />
|
||||||
</div>
|
)}
|
||||||
<div id="Appview">
|
</div>
|
||||||
{templateData["Appview"]?.[0] == "Appview1" && (
|
<div id="Appview">
|
||||||
<ShowcasePreview data={templateData["Appview"][1]?.[0]?.FieldValue} key={"Appview"} />
|
{templateData["Appview"]?.[0] == "Appview1" && (
|
||||||
)}
|
<ShowcasePreview data={templateData["Appview"][1]?.[0]?.FieldValue} key={"Appview"} />
|
||||||
</div>
|
)}
|
||||||
<div id="Testimonials">
|
</div>
|
||||||
{templateData["Testimonials"]?.[0] == "Testimonials1" && (
|
<div id="Testimonials">
|
||||||
<TestimonialPreView isDefault={false} />
|
{templateData["Testimonials"]?.[0] == "Testimonials1" && (
|
||||||
|
<TestimonialPreView isDefault={false} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div id="Features">
|
<div id="Features">
|
||||||
{templateData["Features"]?.[0] == "Features1" && (
|
{templateData["Features"]?.[0] == "Features1" && (
|
||||||
<Features1 data={templateData["Features"][1]} />
|
<Features1 data={templateData["Features"][1]} />
|
||||||
)}
|
)}
|
||||||
{templateData["Features"]?.[0] == "Features2" && (
|
{templateData["Features"]?.[0] == "Features2" && (
|
||||||
<Features2 data={templateData["Features"][1]} />
|
<Features2 data={templateData["Features"][1]} />
|
||||||
)}
|
)}
|
||||||
{templateData["Features"]?.[0] == "Features3" && (
|
{templateData["Features"]?.[0] == "Features3" && (
|
||||||
<Feature3 data={templateData["Features"][1]} />
|
<Feature3 data={templateData["Features"][1]} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div id="Pricing">
|
<div id="Pricing">
|
||||||
{templateData["Pricing"]?.[0] == "Pricing1" && (
|
{templateData["Pricing"]?.[0] == "Pricing1" && (
|
||||||
<Pricing1 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
<Pricing1 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
||||||
)}
|
)}
|
||||||
{templateData["Pricing"]?.[0] == "Pricing2" && (
|
{templateData["Pricing"]?.[0] == "Pricing2" && (
|
||||||
<Pricing2 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
<Pricing2 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
||||||
)}
|
)}
|
||||||
{templateData["Pricing"]?.[0] == "Pricing3" && (
|
{templateData["Pricing"]?.[0] == "Pricing3" && (
|
||||||
<Pricing3 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
<Pricing3 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div id="Faq">
|
<div id="Faq">
|
||||||
{templateData["Faq"]?.[0] == "Faq1" && (
|
{templateData["Faq"]?.[0] == "Faq1" && (
|
||||||
<Faq1 data={templateData["Faq"][1]} />
|
<Faq1 data={templateData["Faq"][1]} />
|
||||||
)}
|
)}
|
||||||
{templateData["Faq"]?.[0] == "Faq2" && (
|
{templateData["Faq"]?.[0] == "Faq2" && (
|
||||||
<Faq2 data={templateData["Faq"][1]} />
|
<Faq2 data={templateData["Faq"][1]} />
|
||||||
)}
|
)}
|
||||||
{templateData["Faq"]?.[0] == "Faq3" && (
|
{templateData["Faq"]?.[0] == "Faq3" && (
|
||||||
<FAQSection data={templateData["Faq"][1]} />
|
<FAQSection data={templateData["Faq"][1]} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div id="CTA">
|
<div id="CTA">
|
||||||
{templateData["CTA"]?.[0] == "CTA1" && (
|
{templateData["CTA"]?.[0] == "CTA1" && (
|
||||||
<CTAPreview data={templateData["CTA"][1]} />
|
<CTAPreview data={templateData["CTA"][1]} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div id="Footer">
|
<div id="Footer">
|
||||||
{templateData["Footer"]?.[0] == "Footer1" && (
|
{templateData["Footer"]?.[0] == "Footer1" && (
|
||||||
<Footer1 data={templateData["Footer"][1]} />
|
<Footer1 data={templateData["Footer"][1]} />
|
||||||
)}
|
)}
|
||||||
{templateData["Footer"]?.[0] == "Footer2" && (
|
{templateData["Footer"]?.[0] == "Footer2" && (
|
||||||
<Footer2 data={templateData["Footer"][1]} />
|
<Footer2 data={templateData["Footer"][1]} />
|
||||||
)}
|
)}
|
||||||
{templateData["Footer"]?.[0] == "Footer3" && (
|
{templateData["Footer"]?.[0] == "Footer3" && (
|
||||||
<FooterTemplate3 data={templateData["Footer"][1]} />
|
<FooterTemplate3 data={templateData["Footer"][1]} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{templateData?.Navbar?.[0] === "Navbar1" && (
|
{templateData?.Navbar?.[0] === "Navbar1" && (
|
||||||
|
|
@ -408,70 +479,72 @@ useEffect(() => {
|
||||||
<HeroSection data={templateData["Overview"][1]} />
|
<HeroSection data={templateData["Overview"][1]} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div id="ShowCase">
|
<Suspense fallback={null}>
|
||||||
{templateData["Showcase"]?.[0] == "Showcase1" && (
|
<div id="ShowCase">
|
||||||
<ShowcasePreview data={templateData["Showcase"][1]?.[0]?.FieldValue} key={"ShowCase"} />
|
{templateData["Showcase"]?.[0] == "Showcase1" && (
|
||||||
)}
|
<ShowcasePreview data={templateData["Showcase"][1]?.[0]?.FieldValue} key={"ShowCase"} />
|
||||||
</div>
|
)}
|
||||||
<div id="Appview">
|
</div>
|
||||||
{templateData["Appview"]?.[0] == "Appview1" && (
|
<div id="Appview">
|
||||||
<ShowcasePreview data={templateData["Appview"][1]?.[0]?.FieldValue} key={"Appview"} />
|
{templateData["Appview"]?.[0] == "Appview1" && (
|
||||||
)}
|
<ShowcasePreview data={templateData["Appview"][1]?.[0]?.FieldValue} key={"Appview"} />
|
||||||
</div>
|
)}
|
||||||
<div id="Testimonials">
|
</div>
|
||||||
{templateData["Testimonials"]?.[0] == "Testimonials1" && (
|
<div id="Testimonials">
|
||||||
<TestimonialPreView isDefault={false} />
|
{templateData["Testimonials"]?.[0] == "Testimonials1" && (
|
||||||
)}
|
<TestimonialPreView isDefault={false} />
|
||||||
</div>
|
)}
|
||||||
<div id="Features">
|
</div>
|
||||||
{templateData["Features"]?.[0] == "Features1" && (
|
<div id="Features">
|
||||||
<Features1 data={templateData["Features"][1]} />
|
{templateData["Features"]?.[0] == "Features1" && (
|
||||||
)}
|
<Features1 data={templateData["Features"][1]} />
|
||||||
{templateData["Features"]?.[0] == "Features2" && (
|
)}
|
||||||
<Features2 data={templateData["Features"][1]} />
|
{templateData["Features"]?.[0] == "Features2" && (
|
||||||
)}
|
<Features2 data={templateData["Features"][1]} />
|
||||||
{templateData["Features"]?.[0] == "Features3" && (
|
)}
|
||||||
<Feature3 data={templateData["Features"][1]} />
|
{templateData["Features"]?.[0] == "Features3" && (
|
||||||
)}
|
<Feature3 data={templateData["Features"][1]} />
|
||||||
</div>
|
)}
|
||||||
<div id="Pricing">
|
</div>
|
||||||
{templateData["Pricing"]?.[0] == "Pricing1" && (
|
<div id="Pricing">
|
||||||
<Pricing1 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
{templateData["Pricing"]?.[0] == "Pricing1" && (
|
||||||
)}
|
<Pricing1 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
||||||
{templateData["Pricing"]?.[0] == "Pricing2" && (
|
)}
|
||||||
<Pricing2 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
{templateData["Pricing"]?.[0] == "Pricing2" && (
|
||||||
)}
|
<Pricing2 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
||||||
{templateData["Pricing"]?.[0] == "Pricing3" && (
|
)}
|
||||||
<Pricing3 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
{templateData["Pricing"]?.[0] == "Pricing3" && (
|
||||||
)}
|
<Pricing3 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
||||||
</div>
|
)}
|
||||||
<div id="Faq">
|
</div>
|
||||||
{templateData["Faq"]?.[0] == "Faq1" && (
|
<div id="Faq">
|
||||||
<Faq1 data={templateData["Faq"][1]} />
|
{templateData["Faq"]?.[0] == "Faq1" && (
|
||||||
)}
|
<Faq1 data={templateData["Faq"][1]} />
|
||||||
{templateData["Faq"]?.[0] == "Faq2" && (
|
)}
|
||||||
<Faq2 data={templateData["Faq"][1]} />
|
{templateData["Faq"]?.[0] == "Faq2" && (
|
||||||
)}
|
<Faq2 data={templateData["Faq"][1]} />
|
||||||
{templateData["Faq"]?.[0] == "Faq3" && (
|
)}
|
||||||
<FAQSection data={templateData["Faq"][1]} />
|
{templateData["Faq"]?.[0] == "Faq3" && (
|
||||||
)}
|
<FAQSection data={templateData["Faq"][1]} />
|
||||||
</div>
|
)}
|
||||||
<div id="CTA">
|
</div>
|
||||||
{templateData["CTA"]?.[0] == "CTA1" && (
|
<div id="CTA">
|
||||||
<CTAPreview data={templateData["CTA"][1]} />
|
{templateData["CTA"]?.[0] == "CTA1" && (
|
||||||
)}
|
<CTAPreview data={templateData["CTA"][1]} />
|
||||||
</div>
|
)}
|
||||||
<div id="Footer">
|
</div>
|
||||||
{templateData["Footer"]?.[0] == "Footer1" && (
|
<div id="Footer">
|
||||||
<Footer1 data={templateData["Footer"][1]} />
|
{templateData["Footer"]?.[0] == "Footer1" && (
|
||||||
)}
|
<Footer1 data={templateData["Footer"][1]} />
|
||||||
{templateData["Footer"]?.[0] == "Footer2" && (
|
)}
|
||||||
<Footer2 data={templateData["Footer"][1]} />
|
{templateData["Footer"]?.[0] == "Footer2" && (
|
||||||
)}
|
<Footer2 data={templateData["Footer"][1]} />
|
||||||
{templateData["Footer"]?.[0] == "Footer3" && (
|
)}
|
||||||
<FooterTemplate3 data={templateData["Footer"][1]} />
|
{templateData["Footer"]?.[0] == "Footer3" && (
|
||||||
)}
|
<FooterTemplate3 data={templateData["Footer"][1]} />
|
||||||
</div>
|
)}
|
||||||
|
</div>
|
||||||
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{templateData?.Navbar?.[0] === "Navbar3" && (
|
{templateData?.Navbar?.[0] === "Navbar3" && (
|
||||||
|
|
@ -501,94 +574,96 @@ useEffect(() => {
|
||||||
<HeroSection data={templateData["Overview"][1]} />
|
<HeroSection data={templateData["Overview"][1]} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div id="ShowCase">
|
<Suspense fallback={null}>
|
||||||
{templateData["Showcase"]?.[0] == "Showcase1" && (
|
<div id="ShowCase">
|
||||||
<ShowcasePreview data={templateData["Showcase"][1]?.[0]?.FieldValue} key={"ShowCase"} />
|
{templateData["Showcase"]?.[0] == "Showcase1" && (
|
||||||
)}
|
<ShowcasePreview data={templateData["Showcase"][1]?.[0]?.FieldValue} key={"ShowCase"} />
|
||||||
</div>
|
)}
|
||||||
<div id="Appview">
|
</div>
|
||||||
{templateData["Appview"]?.[0] == "Appview1" && (
|
<div id="Appview">
|
||||||
<ShowcasePreview data={templateData["Appview"][1]?.[0]?.FieldValue} key={"Appview"} />
|
{templateData["Appview"]?.[0] == "Appview1" && (
|
||||||
)}
|
<ShowcasePreview data={templateData["Appview"][1]?.[0]?.FieldValue} key={"Appview"} />
|
||||||
</div>
|
)}
|
||||||
<div id="Testimonials">
|
</div>
|
||||||
{templateData["Testimonials"]?.[0] == "Testimonials1" && (
|
<div id="Testimonials">
|
||||||
<TestimonialPreView isDefault={false} />)}
|
{templateData["Testimonials"]?.[0] == "Testimonials1" && (
|
||||||
</div>
|
<TestimonialPreView isDefault={false} />)}
|
||||||
<div id="Features">
|
</div>
|
||||||
{templateData["Features"]?.[0] == "Features1" && (
|
<div id="Features">
|
||||||
<Features1 data={templateData["Features"][1]} />
|
{templateData["Features"]?.[0] == "Features1" && (
|
||||||
)}
|
<Features1 data={templateData["Features"][1]} />
|
||||||
{templateData["Features"]?.[0] == "Features2" && (
|
)}
|
||||||
<Features2 data={templateData["Features"][1]} />
|
{templateData["Features"]?.[0] == "Features2" && (
|
||||||
)}
|
<Features2 data={templateData["Features"][1]} />
|
||||||
{templateData["Features"]?.[0] == "Features3" && (
|
)}
|
||||||
<Feature3 data={templateData["Features"][1]} />
|
{templateData["Features"]?.[0] == "Features3" && (
|
||||||
)}
|
<Feature3 data={templateData["Features"][1]} />
|
||||||
</div>
|
)}
|
||||||
<div id="Pricing">
|
</div>
|
||||||
{templateData["Pricing"]?.[0] == "Pricing1" && (
|
<div id="Pricing">
|
||||||
<Pricing1 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
{templateData["Pricing"]?.[0] == "Pricing1" && (
|
||||||
)}
|
<Pricing1 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
||||||
{templateData["Pricing"]?.[0] == "Pricing2" && (
|
)}
|
||||||
<Pricing2 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
{templateData["Pricing"]?.[0] == "Pricing2" && (
|
||||||
)}
|
<Pricing2 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
||||||
{templateData["Pricing"]?.[0] == "Pricing3" && (
|
)}
|
||||||
<Pricing3 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
{templateData["Pricing"]?.[0] == "Pricing3" && (
|
||||||
)}
|
<Pricing3 data={templateData["Pricing"][1]} AdminId={AdminId ? AdminId : location?.state?.AdminId} />
|
||||||
</div>
|
)}
|
||||||
<div id="Faq">
|
</div>
|
||||||
{templateData["Faq"]?.[0] == "Faq1" && (
|
<div id="Faq">
|
||||||
<Faq1 data={templateData["Faq"][1]} />
|
{templateData["Faq"]?.[0] == "Faq1" && (
|
||||||
)}
|
<Faq1 data={templateData["Faq"][1]} />
|
||||||
{templateData["Faq"]?.[0] == "Faq2" && (
|
)}
|
||||||
<Faq2 data={templateData["Faq"][1]} />
|
{templateData["Faq"]?.[0] == "Faq2" && (
|
||||||
)}
|
<Faq2 data={templateData["Faq"][1]} />
|
||||||
{/* {templateData["Faq"]?.[0] == "Faq3" && (
|
)}
|
||||||
<FAQSection data={templateData["Faq"][1]} />
|
{/* {templateData["Faq"]?.[0] == "Faq3" && (
|
||||||
</div>
|
<FAQSection data={templateData["Faq"][1]} />
|
||||||
)} */}
|
</div>
|
||||||
{templateData["Faq"]?.[0] === "Faq3" && (
|
)} */}
|
||||||
<div style={{
|
{templateData["Faq"]?.[0] === "Faq3" && (
|
||||||
margin:"0 0 2rem 0", width:"100%",
|
<div style={{
|
||||||
display:"flex", alignItems:"center", flexDirection:"row", justifyContent:"center", gap:"1rem"
|
margin:"0 0 2rem 0", width:"100%",
|
||||||
}}>
|
display:"flex", alignItems:"center", flexDirection:"row", justifyContent:"center", gap:"1rem"
|
||||||
<div style={{fontSize:"16px",fontWeight:"600", margin:"1rem 0",
|
}}>
|
||||||
fontFamily: CurrentText?.head ? CurrentText?.head : '',
|
<div style={{fontSize:"16px",fontWeight:"600", margin:"1rem 0",
|
||||||
}}>View complete FAQ list</div>
|
fontFamily: CurrentText?.head ? CurrentText?.head : '',
|
||||||
<button
|
}}>View complete FAQ list</div>
|
||||||
scrollToId="backFaq"
|
<button
|
||||||
onClick={() => navigate( `${subDirectory}Faq`,
|
scrollToId="backFaq"
|
||||||
{ state: { faqData: templateData["Faq"][1], from: location.pathname, } }
|
onClick={() => navigate( `${subDirectory}Faq`,
|
||||||
)}
|
{ state: { faqData: templateData["Faq"][1], from: location.pathname, } }
|
||||||
style={{
|
)}
|
||||||
fontFamily: CurrentText?.para ? CurrentText?.para : '', gap:"10px", border:"none",
|
style={{
|
||||||
backgroundColor: 'unset', display:"flex", alignItems:"center",
|
fontFamily: CurrentText?.para ? CurrentText?.para : '', gap:"10px", border:"none",
|
||||||
color:"#000", cursor:"pointer" , borderBottom:"1px solid #000"
|
backgroundColor: 'unset', display:"flex", alignItems:"center",
|
||||||
}}
|
color:"#000", cursor:"pointer" , borderBottom:"1px solid #000"
|
||||||
>
|
}}
|
||||||
See all FAQs <LuMousePointerClick size={24}/>
|
>
|
||||||
</button>
|
See all FAQs <LuMousePointerClick size={24}/>
|
||||||
{/* <FAQSection data={templateData["Faq"][1]} /> */}
|
</button>
|
||||||
</div>
|
{/* <FAQSection data={templateData["Faq"][1]} /> */}
|
||||||
)}
|
</div>
|
||||||
</div>
|
)}
|
||||||
<div id="CTA">
|
</div>
|
||||||
{templateData["CTA"]?.[0] == "CTA1" && (
|
<div id="CTA">
|
||||||
<CTAPreview data={templateData["CTA"][1]} />
|
{templateData["CTA"]?.[0] == "CTA1" && (
|
||||||
)}
|
<CTAPreview data={templateData["CTA"][1]} />
|
||||||
</div>
|
)}
|
||||||
<div id="Footer">
|
</div>
|
||||||
{templateData["Footer"]?.[0] == "Footer1" && (
|
<div id="Footer">
|
||||||
<Footer1 data={templateData["Footer"][1]} />
|
{templateData["Footer"]?.[0] == "Footer1" && (
|
||||||
)}
|
<Footer1 data={templateData["Footer"][1]} />
|
||||||
{templateData["Footer"]?.[0] == "Footer2" && (
|
)}
|
||||||
<Footer2 data={templateData["Footer"][1]} />
|
{templateData["Footer"]?.[0] == "Footer2" && (
|
||||||
)}
|
<Footer2 data={templateData["Footer"][1]} />
|
||||||
{templateData["Footer"]?.[0] == "Footer3" && (
|
)}
|
||||||
<FooterTemplate3 data={templateData["Footer"][1]} />
|
{templateData["Footer"]?.[0] == "Footer3" && (
|
||||||
)}
|
<FooterTemplate3 data={templateData["Footer"][1]} />
|
||||||
</div>
|
)}
|
||||||
|
</div>
|
||||||
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,15 @@ const ContactUs = () => {
|
||||||
if (industry) {
|
if (industry) {
|
||||||
handleIndustry();
|
handleIndustry();
|
||||||
}
|
}
|
||||||
|
// Clean URL: Remove special chars, convert spaces to hyphens
|
||||||
|
const cleanUrl = AppName
|
||||||
|
.replace(/[,]/g, '') // Remove commas
|
||||||
|
.replace(/\s+/g, '-') // Spaces to hyphens
|
||||||
|
.replace(/&/g, 'and') // & to 'and'
|
||||||
|
.replace(/[^a-z0-9-]/gi, '') // Remove other special chars
|
||||||
|
.toLowerCase();
|
||||||
|
navigate(`${subDirectory}${cleanUrl}`);
|
||||||
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState, useMemo } from "react";
|
||||||
import "../Styles/Footer.scss";
|
import "../Styles/Footer.scss";
|
||||||
import pozominilogo from "../Images/pozominilogo.webp";
|
import pozominilogo from "../Images/pozominilogo.webp";
|
||||||
import { PiInstagramLogoFill } from "react-icons/pi";
|
import { PiInstagramLogoFill } from "react-icons/pi";
|
||||||
import { FaFacebook } from "react-icons/fa";
|
import { FaFacebook } from "react-icons/fa";
|
||||||
import { RiTwitterXFill } from "react-icons/ri";
|
import { RiTwitterXFill } from "react-icons/ri";
|
||||||
import { FaYoutube } from "react-icons/fa";
|
import { FaYoutube } from "react-icons/fa";
|
||||||
import { getApplicationData } from "../../features/publicHome/publicHome";
|
import { BiSearch } from "react-icons/bi";
|
||||||
import { useDispatch } from "react-redux";
|
|
||||||
import { gsap } from "gsap";
|
import { gsap } from "gsap";
|
||||||
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
@ -14,46 +13,24 @@ import { sessionStore } from "../../Services/others";
|
||||||
|
|
||||||
gsap.registerPlugin(ScrollTrigger);
|
gsap.registerPlugin(ScrollTrigger);
|
||||||
const subDirectory = import.meta.env.ENV_BASE_URL
|
const subDirectory = import.meta.env.ENV_BASE_URL
|
||||||
const Footer = () => {
|
const Footer = ({ AppCategory = [] }) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const logoRef = useRef(null);
|
const logoRef = useRef(null);
|
||||||
const productsRef = useRef(null);
|
const productsRef = useRef(null);
|
||||||
const footerRef = useRef(null);
|
const footerRef = useRef(null);
|
||||||
const dispatch = useDispatch();
|
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [message, setMessage] = useState("");
|
const [message, setMessage] = useState("");
|
||||||
const [messageType, setMessageType] = useState("");
|
const [messageType, setMessageType] = useState("");
|
||||||
const [appList, setAppList] = useState([]);
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const [isFooterVisible, setIsFooterVisible] = useState(false);
|
const [filteredApps, setFilteredApps] = useState([]);
|
||||||
|
const [currentCategoryPage, setCurrentCategoryPage] = useState(0);
|
||||||
|
|
||||||
const scrollToTop = () => {
|
const scrollToTop = () => {
|
||||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Intersection Observer for lazy loading
|
|
||||||
const observer = new IntersectionObserver(
|
|
||||||
(entries) => {
|
|
||||||
entries.forEach((entry) => {
|
|
||||||
console.log("👁️ Footer visibility:", entry.isIntersecting);
|
|
||||||
if (entry.isIntersecting && !isFooterVisible) {
|
|
||||||
console.log("🎯 Footer is visible! Loading apps...");
|
|
||||||
setIsFooterVisible(true);
|
|
||||||
fetchApplicationData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
{ threshold: 0.1 }
|
|
||||||
);
|
|
||||||
|
|
||||||
if (footerRef.current) {
|
|
||||||
console.log("✅ Observer attached to footer");
|
|
||||||
observer.observe(footerRef.current);
|
|
||||||
} else {
|
|
||||||
console.log("❌ footerRef is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logo animation
|
// Logo animation
|
||||||
if (logoRef.current) {
|
if (logoRef.current) {
|
||||||
gsap.fromTo(
|
gsap.fromTo(
|
||||||
|
|
@ -92,36 +69,159 @@ const Footer = () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
|
||||||
if (footerRef.current) {
|
|
||||||
observer.unobserve(footerRef.current);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchApplicationData = async () => {
|
|
||||||
try {
|
|
||||||
console.log("🔥 Footer: Fetching apps data...");
|
|
||||||
const res = await dispatch(getApplicationData())?.unwrap();
|
|
||||||
console.log("📦 Footer API Response:", res?.data);
|
|
||||||
if (res?.data?.statusCode === 1) {
|
|
||||||
const activeApps = res?.data?.data?.filter(app => app.ActiveStatus === "A") || [];
|
|
||||||
console.log("✅ Footer Active Apps:", activeApps.length, activeApps);
|
|
||||||
setAppList(activeApps);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("❌ Error fetching apps:", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const redirectApp = (appName, appId) => {
|
const redirectApp = (appName, appId) => {
|
||||||
sessionStore("AppId", appId);
|
sessionStore("AppId", appId);
|
||||||
sessionStore("AppName", appName);
|
sessionStore("AppName", appName);
|
||||||
navigate(`${subDirectory}${appName}`);
|
// Clean URL: Remove special chars, convert spaces to hyphens
|
||||||
|
const cleanUrl = appName
|
||||||
|
.replace(/[,]/g, '') // Remove commas
|
||||||
|
.replace(/\s+/g, '-') // Spaces to hyphens
|
||||||
|
.replace(/&/g, 'and') // & to 'and'
|
||||||
|
.replace(/[^a-z0-9-]/gi, '') // Remove other special chars
|
||||||
|
.toLowerCase();
|
||||||
|
navigate(`${subDirectory}${cleanUrl}`);
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Categorize apps (EXACT same logic as IndustriesList)
|
||||||
|
const categorizeApps = (apps) => {
|
||||||
|
const categories = {
|
||||||
|
// Consumer (Retail Universe)
|
||||||
|
foodBeverages: [],
|
||||||
|
wellness: [],
|
||||||
|
fashion: [],
|
||||||
|
electronics: [],
|
||||||
|
grocery: [],
|
||||||
|
services: [],
|
||||||
|
others: [],
|
||||||
|
// Manufacturing & Healthcare
|
||||||
|
healthcare: [],
|
||||||
|
manufacturing: [],
|
||||||
|
// Transportation & Hospitality
|
||||||
|
transportation: [],
|
||||||
|
hospitality: []
|
||||||
|
};
|
||||||
|
|
||||||
|
apps.forEach(app => {
|
||||||
|
const name = app.AppName?.toLowerCase() || "";
|
||||||
|
const category = app.CategoryName?.toLowerCase() || "";
|
||||||
|
|
||||||
|
// Consumer categories
|
||||||
|
if (/(consumer)/i.test(category)) {
|
||||||
|
if (/(bakery|restaurant|dairy|food|cafe|coffee|ice|pickle|pozoresto|resto|eatery|diner|bistro|pizz|burger|juice|sweet|snack)/i.test(name)) {
|
||||||
|
categories.foodBeverages.push(app);
|
||||||
|
} else if (/(salon|spa|beauty|cosmetics|fitness|gym|yoga|wellness|massage|parlour|parlor)/i.test(name)) {
|
||||||
|
categories.wellness.push(app);
|
||||||
|
} else if (/(fashion|jewellery|jewelry|footwear|lifestyle|apparel|textile|cloth|garment|shoe|sandal|accessory)/i.test(name)) {
|
||||||
|
categories.fashion.push(app);
|
||||||
|
} else if (/(electronic|mobile|computer|appliance|laptop|phone|device|gadget|tech)/i.test(name)) {
|
||||||
|
categories.electronics.push(app);
|
||||||
|
} else if (/(grocery|departmental|wholesale|supermarket|mart|retail|store)/i.test(name)) {
|
||||||
|
categories.grocery.push(app);
|
||||||
|
} else if (/(stationery|xerox|print|coaching|cement|tuition|education|training|class)/i.test(name)) {
|
||||||
|
categories.services.push(app);
|
||||||
|
} else {
|
||||||
|
categories.others.push(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Healthcare & Pharma
|
||||||
|
else if (/(healthcare|pharma)/i.test(category) || /(health|optical)/i.test(name)) {
|
||||||
|
categories.healthcare.push(app);
|
||||||
|
}
|
||||||
|
// Manufacturing
|
||||||
|
else if (/(manufacturing)/i.test(category) || /(manufacturer)/i.test(name)) {
|
||||||
|
categories.manufacturing.push(app);
|
||||||
|
}
|
||||||
|
// Transportation & Logistics
|
||||||
|
else if (/(transportation|logistics)/i.test(category) || /(parking|boating)/i.test(name)) {
|
||||||
|
categories.transportation.push(app);
|
||||||
|
}
|
||||||
|
// Hospitality & Entertainment
|
||||||
|
else if (/(hospitality|entertainment)/i.test(category) || /(hotel|resort)/i.test(name)) {
|
||||||
|
categories.hospitality.push(app);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return categories;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 🚀 Memoize categorization - Only recalculate when AppCategory changes
|
||||||
|
const categorizedApps = useMemo(() => categorizeApps(AppCategory), [AppCategory]);
|
||||||
|
|
||||||
|
// 🔍 Search/Filter logic
|
||||||
|
useEffect(() => {
|
||||||
|
if (searchTerm.trim() === "") {
|
||||||
|
setFilteredApps([]);
|
||||||
|
} else {
|
||||||
|
const filtered = AppCategory.filter(app =>
|
||||||
|
app.AppName?.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
|
);
|
||||||
|
setFilteredApps(filtered);
|
||||||
|
}
|
||||||
|
}, [searchTerm, AppCategory]);
|
||||||
|
|
||||||
|
const handleSearchChange = (e) => {
|
||||||
|
setSearchTerm(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearSearch = () => {
|
||||||
|
setSearchTerm("");
|
||||||
|
};
|
||||||
|
|
||||||
|
// Organize all categories for pagination
|
||||||
|
const allCategories = useMemo(() => {
|
||||||
|
const cats = [];
|
||||||
|
if (categorizedApps.foodBeverages.length > 0) {
|
||||||
|
cats.push({ title: "Food & Beverages", apps: categorizedApps.foodBeverages });
|
||||||
|
}
|
||||||
|
if (categorizedApps.wellness.length > 0) {
|
||||||
|
cats.push({ title: "Wellness & Beauty", apps: categorizedApps.wellness });
|
||||||
|
}
|
||||||
|
if (categorizedApps.fashion.length > 0) {
|
||||||
|
cats.push({ title: "Fashion & Lifestyle", apps: categorizedApps.fashion });
|
||||||
|
}
|
||||||
|
if (categorizedApps.electronics.length > 0) {
|
||||||
|
cats.push({ title: "Electronics & Tech", apps: categorizedApps.electronics });
|
||||||
|
}
|
||||||
|
if (categorizedApps.grocery.length > 0) {
|
||||||
|
cats.push({ title: "Grocery & Retail", apps: categorizedApps.grocery });
|
||||||
|
}
|
||||||
|
if (categorizedApps.services.length > 0) {
|
||||||
|
cats.push({ title: "Services", apps: categorizedApps.services });
|
||||||
|
}
|
||||||
|
if (categorizedApps.healthcare.length > 0) {
|
||||||
|
cats.push({ title: "Healthcare & Pharma", apps: categorizedApps.healthcare });
|
||||||
|
}
|
||||||
|
if (categorizedApps.manufacturing.length > 0) {
|
||||||
|
cats.push({ title: "Manufacturing", apps: categorizedApps.manufacturing });
|
||||||
|
}
|
||||||
|
if (categorizedApps.transportation.length > 0) {
|
||||||
|
cats.push({ title: "Transportation", apps: categorizedApps.transportation });
|
||||||
|
}
|
||||||
|
if (categorizedApps.hospitality.length > 0) {
|
||||||
|
cats.push({ title: "Hospitality", apps: categorizedApps.hospitality });
|
||||||
|
}
|
||||||
|
if (categorizedApps.others.length > 0) {
|
||||||
|
cats.push({ title: "More Industries", apps: categorizedApps.others });
|
||||||
|
}
|
||||||
|
return cats;
|
||||||
|
}, [categorizedApps]);
|
||||||
|
|
||||||
|
const categoriesPerPage = 3;
|
||||||
|
const totalPages = Math.ceil(allCategories.length / categoriesPerPage);
|
||||||
|
const startIndex = currentCategoryPage * categoriesPerPage;
|
||||||
|
const visibleCategories = allCategories.slice(startIndex, startIndex + categoriesPerPage);
|
||||||
|
|
||||||
|
const handlePrevPage = () => {
|
||||||
|
setCurrentCategoryPage((prev) => Math.max(0, prev - 1));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNextPage = () => {
|
||||||
|
setCurrentCategoryPage((prev) => Math.min(totalPages - 1, prev + 1));
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubscribe = async () => {
|
const handleSubscribe = async () => {
|
||||||
if (!email) {
|
if (!email) {
|
||||||
setMessage("Please enter your email address");
|
setMessage("Please enter your email address");
|
||||||
|
|
@ -177,7 +277,7 @@ const Footer = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="clutter">
|
<div className="clutter">
|
||||||
Stay informed with only what matters <br /> —no spam, no clutter.
|
Stay informed with only what matters <br />—no spam, no clutter.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <div className="inputOfFooter">
|
{/* <div className="inputOfFooter">
|
||||||
|
|
@ -201,42 +301,118 @@ const Footer = () => {
|
||||||
|
|
||||||
<div className="footerRight">
|
<div className="footerRight">
|
||||||
<div className="footerProducts" ref={productsRef}>
|
<div className="footerProducts" ref={productsRef}>
|
||||||
<div>Products</div>
|
{/* Top Bar: Title + Search + Navigation in one line */}
|
||||||
{(() => {
|
<div className="products-top-bar">
|
||||||
console.log("🔍 Rendering Footer Products:");
|
<div className="products-heading">Products</div>
|
||||||
console.log(" - isFooterVisible:", isFooterVisible);
|
|
||||||
console.log(" - appList.length:", appList.length);
|
{/* Search Box */}
|
||||||
console.log(" - Showing:", isFooterVisible && appList.length > 0 ? "Dynamic" : "Static");
|
<div className="products-search-box">
|
||||||
return null;
|
<BiSearch className="products-search-icon" />
|
||||||
})()}
|
<input
|
||||||
{isFooterVisible && appList.length > 0 ? (
|
type="text"
|
||||||
appList.slice(0, 15).map((app) => (
|
placeholder="Search products..."
|
||||||
<p
|
value={searchTerm}
|
||||||
key={app.AppId}
|
onChange={handleSearchChange}
|
||||||
onClick={() => redirectApp(app.AppName?.toLowerCase(), app.AppId)}
|
className="products-search-input"
|
||||||
style={{ cursor: 'pointer' }}
|
/>
|
||||||
>
|
{searchTerm && (
|
||||||
{app.AppName}
|
<button onClick={clearSearch} className="products-search-clear">
|
||||||
</p>
|
✕
|
||||||
))
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Navigation Controls */}
|
||||||
|
{!searchTerm && (
|
||||||
|
<div className="footer-navigation">
|
||||||
|
<button
|
||||||
|
onClick={handlePrevPage}
|
||||||
|
disabled={currentCategoryPage === 0}
|
||||||
|
className="footer-nav-btn"
|
||||||
|
>
|
||||||
|
‹
|
||||||
|
</button>
|
||||||
|
<div className="footer-page-indicator">
|
||||||
|
{currentCategoryPage + 1} / {totalPages}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={handleNextPage}
|
||||||
|
disabled={currentCategoryPage === totalPages - 1}
|
||||||
|
className="footer-nav-btn"
|
||||||
|
>
|
||||||
|
›
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Search Results Count */}
|
||||||
|
{searchTerm && (
|
||||||
|
<div className="products-search-results-count">
|
||||||
|
{filteredApps.length} {filteredApps.length === 1 ? 'result' : 'results'} found
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{searchTerm && filteredApps.length > 0 ? (
|
||||||
|
// Search Results
|
||||||
|
<div className="footer-search-results">
|
||||||
|
{filteredApps.map((app) => (
|
||||||
|
<p
|
||||||
|
key={app.AppId}
|
||||||
|
onClick={() => redirectApp(app.AppName?.toLowerCase(), app.AppId)}
|
||||||
|
className="search-result-item"
|
||||||
|
>
|
||||||
|
{app.AppName}
|
||||||
|
</p>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : searchTerm && filteredApps.length === 0 ? (
|
||||||
|
// No Results
|
||||||
|
<div className="footer-no-results">
|
||||||
|
<p>No products found for "{searchTerm}"</p>
|
||||||
|
</div>
|
||||||
|
) : AppCategory.length > 0 ? (
|
||||||
|
<div className="footer-columns-wrapper">
|
||||||
|
{visibleCategories.map((category, index) => (
|
||||||
|
<div className="footer-column" key={index}>
|
||||||
|
<div className="footer-category">{category.title}</div>
|
||||||
|
{category.apps.map((app) => (
|
||||||
|
<p
|
||||||
|
key={app.AppId}
|
||||||
|
onClick={() => redirectApp(app.AppName?.toLowerCase(), app.AppId)}
|
||||||
|
>
|
||||||
|
{app.AppName}
|
||||||
|
</p>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<div className="footer-columns-wrapper">
|
||||||
<p>Restaurant</p>
|
{/* Column 1 - Static */}
|
||||||
<p>Bakery</p>
|
<div className="footer-column">
|
||||||
<p>Dairy Delights</p>
|
<div className="footer-category">Food & Beverages</div>
|
||||||
<p>Electrical, Electronics and Computers</p>
|
<p onClick={() => navigate(`${subDirectory}dairy-delights`)}>Dairy Delights</p>
|
||||||
<p>Mobile & Accessories</p>
|
<p onClick={() => navigate(`${subDirectory}restaurant`)}>Restaurant</p>
|
||||||
<p>Groceries</p>
|
<p onClick={() => navigate(`${subDirectory}bakery`)}>Bakery</p>
|
||||||
<p>Cement</p>
|
</div>
|
||||||
<p>Lifestyle and Fashion</p>
|
|
||||||
<p>Fashion Jewellery</p>
|
{/* Column 2 - Static */}
|
||||||
<p>Footwear</p>
|
<div className="footer-column">
|
||||||
<p>Salon, Spa and Beauty Parlour</p>
|
<div className="footer-category">Wellness & Beauty</div>
|
||||||
<p>Beauty and Cosmetics shop</p>
|
<p onClick={() => navigate(`${subDirectory}beauty-and-cosmetics-shop`)}>Beauty and Cosmetics shop</p>
|
||||||
<p>Fitness</p>
|
<p onClick={() => navigate(`${subDirectory}fitness`)}>Fitness</p>
|
||||||
<p>Departmental Stores</p>
|
<p onClick={() => navigate(`${subDirectory}salon-spa-and-beauty-parlour`)}>Salon, Spa and Beauty Parlour</p>
|
||||||
<p>Wholesale</p>
|
</div>
|
||||||
</>
|
|
||||||
|
{/* Column 3 - Static */}
|
||||||
|
<div className="footer-column">
|
||||||
|
<div className="footer-category">Fashion & Lifestyle</div>
|
||||||
|
<p onClick={() => navigate(`${subDirectory}lifestyle-and-fashion`)}>Lifestyle and Fashion</p>
|
||||||
|
<p onClick={() => navigate(`${subDirectory}fashion-jewellery`)}>Fashion Jewellery</p>
|
||||||
|
<p onClick={() => navigate(`${subDirectory}footwear`)}>Footwear</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,14 @@ const Industries = () => {
|
||||||
const redirectApp = (AppName, AppId) => {
|
const redirectApp = (AppName, AppId) => {
|
||||||
sessionStore("AppId", AppId);
|
sessionStore("AppId", AppId);
|
||||||
sessionStore("AppName", AppName);
|
sessionStore("AppName", AppName);
|
||||||
navigate(`${subDirectory}${AppName}`);
|
// Clean URL: Remove special chars, convert spaces to hyphens
|
||||||
|
const cleanUrl = AppName
|
||||||
|
.replace(/[,]/g, '') // Remove commas
|
||||||
|
.replace(/\s+/g, '-') // Spaces to hyphens
|
||||||
|
.replace(/&/g, 'and') // & to 'and'
|
||||||
|
.replace(/[^a-z0-9-]/gi, '') // Remove other special chars
|
||||||
|
.toLowerCase();
|
||||||
|
navigate(`${subDirectory}${cleanUrl}`);
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { HiMiniArrowUpRight } from "react-icons/hi2";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import { clearSession, getSession, sessionStore } from "../../Services/others";
|
import { clearSession, getSession, sessionStore } from "../../Services/others";
|
||||||
|
|
||||||
import { FaChevronDown } from "react-icons/fa";
|
import { FaChevronDown, FaWhatsapp } from "react-icons/fa";
|
||||||
import IndustriesList from "./IndustriesList";
|
import IndustriesList from "./IndustriesList";
|
||||||
import { IoClose } from "react-icons/io5";
|
import { IoClose } from "react-icons/io5";
|
||||||
import { HiMenu } from "react-icons/hi";
|
import { HiMenu } from "react-icons/hi";
|
||||||
|
|
@ -81,6 +81,17 @@ const Navbar = ({
|
||||||
setIndustryRes(!industryRes);
|
setIndustryRes(!industryRes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [solutionsOpen, setSolutionsOpen] = useState(false);
|
||||||
|
const [solutionsOpenRes, setSolutionsOpenRes] = useState(false);
|
||||||
|
|
||||||
|
const handleSolutions = () => {
|
||||||
|
setSolutionsOpen(!solutionsOpen);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSolutionsRes = () => {
|
||||||
|
setSolutionsOpenRes(!solutionsOpenRes);
|
||||||
|
};
|
||||||
|
|
||||||
const handleNavbarResponsive = () => {
|
const handleNavbarResponsive = () => {
|
||||||
// Force scroll to top with immediate execution
|
// Force scroll to top with immediate execution
|
||||||
document.documentElement.scrollTop = 0;
|
document.documentElement.scrollTop = 0;
|
||||||
|
|
@ -120,7 +131,7 @@ const Navbar = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePricing = () => {
|
const handlePricing = () => {
|
||||||
navigate(`${subDirectory}pricing-pozoapp`);
|
navigate(`${subDirectory}pricing`);
|
||||||
};
|
};
|
||||||
const handleNavigatePrivacy = () => {
|
const handleNavigatePrivacy = () => {
|
||||||
navigate(`${subDirectory}privacy-policy`);
|
navigate(`${subDirectory}privacy-policy`);
|
||||||
|
|
@ -166,7 +177,14 @@ const Navbar = ({
|
||||||
const redirectApp = (AppName, AppId) => {
|
const redirectApp = (AppName, AppId) => {
|
||||||
sessionStore("AppId", AppId);
|
sessionStore("AppId", AppId);
|
||||||
sessionStore("AppName", AppName);
|
sessionStore("AppName", AppName);
|
||||||
navigate(`${subDirectory}${AppName}`);
|
// Clean URL: Remove special chars, convert spaces to hyphens
|
||||||
|
const cleanUrl = AppName
|
||||||
|
.replace(/[,]/g, '') // Remove commas
|
||||||
|
.replace(/\s+/g, '-') // Spaces to hyphens
|
||||||
|
.replace(/&/g, 'and') // & to 'and'
|
||||||
|
.replace(/[^a-z0-9-]/gi, '') // Remove other special chars
|
||||||
|
.toLowerCase();
|
||||||
|
navigate(`${subDirectory}${cleanUrl}`);
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -298,6 +316,14 @@ const Navbar = ({
|
||||||
PozoApp
|
PozoApp
|
||||||
</div>
|
</div>
|
||||||
<div className="navbarOption">
|
<div className="navbarOption">
|
||||||
|
<p onClick={navigateAndScrollToTop}>Home</p>
|
||||||
|
<p
|
||||||
|
onClick={handleSolutions}
|
||||||
|
style={{ color: solutionsOpen ? "#1473f8ff" : "" }}
|
||||||
|
>
|
||||||
|
Solutions{" "}
|
||||||
|
{solutionsOpen ? <FaChevronUp size={10} /> : <FaChevronDown size={10} />}
|
||||||
|
</p>
|
||||||
<p
|
<p
|
||||||
onClick={handleIndustry}
|
onClick={handleIndustry}
|
||||||
style={{ color: industry ? "#1473f8ff" : "" }}
|
style={{ color: industry ? "#1473f8ff" : "" }}
|
||||||
|
|
@ -305,7 +331,6 @@ const Navbar = ({
|
||||||
Industries{" "}
|
Industries{" "}
|
||||||
{industry ? <FaChevronUp size={10} /> : <FaChevronDown size={10} />}
|
{industry ? <FaChevronUp size={10} /> : <FaChevronDown size={10} />}
|
||||||
</p>
|
</p>
|
||||||
<p onClick={scrollToSection}>Offerings </p>
|
|
||||||
<p
|
<p
|
||||||
onClick={handleCompanyList}
|
onClick={handleCompanyList}
|
||||||
style={{ color: company ? "#1473f8ff" : "" }}
|
style={{ color: company ? "#1473f8ff" : "" }}
|
||||||
|
|
@ -313,10 +338,36 @@ const Navbar = ({
|
||||||
Company{" "}
|
Company{" "}
|
||||||
{company ? <FaChevronUp size={10} /> : <FaChevronDown size={10} />}
|
{company ? <FaChevronUp size={10} /> : <FaChevronDown size={10} />}
|
||||||
</p>
|
</p>
|
||||||
<p onClick={handleBlogPage}>Blog</p>
|
|
||||||
<p onClick={handlePricing}>Pricing</p>
|
<p onClick={handlePricing}>Pricing</p>
|
||||||
<p onClick={handleNavigateContact}>Contact Us </p>
|
<p onClick={handleBlogPage}>Blog</p>
|
||||||
|
<p onClick={() => navigate(`${subDirectory}case-studies`)}>Case Studies</p>
|
||||||
|
<p onClick={handleNavigateContact}>Contact Us</p>
|
||||||
</div>
|
</div>
|
||||||
|
{solutionsOpen && (
|
||||||
|
<div className="solutions-dropdown">
|
||||||
|
<div className="solutions-list">
|
||||||
|
<div className="solution-item" onClick={() => navigate(`${subDirectory}solutions/retail-billing`)}>
|
||||||
|
<span>Retail Billing</span>
|
||||||
|
</div>
|
||||||
|
<div className="solution-item" onClick={() => navigate(`${subDirectory}solutions/inventory-purchase`)}>
|
||||||
|
<span>Inventory & Purchase</span>
|
||||||
|
</div>
|
||||||
|
<div className="solution-item" onClick={() => navigate(`${subDirectory}solutions/weighing-scale-pos`)}>
|
||||||
|
<span>Weighing Scale POS</span>
|
||||||
|
</div>
|
||||||
|
<div className="solution-item" onClick={() => navigate(`${subDirectory}solutions/multi-store-erp`)}>
|
||||||
|
<span>Multi-Store ERP</span>
|
||||||
|
</div>
|
||||||
|
<div className="solution-item" onClick={() => navigate(`${subDirectory}solutions/gst-billing-e-invoice`)}>
|
||||||
|
<span>GST Billing & E-Invoice</span>
|
||||||
|
</div>
|
||||||
|
<div className="solution-item" onClick={() => navigate(`${subDirectory}solutions/offline-billing`)}>
|
||||||
|
<span>Offline Billing</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{industry && (
|
{industry && (
|
||||||
<IndustriesList
|
<IndustriesList
|
||||||
industryRef={industryRef}
|
industryRef={industryRef}
|
||||||
|
|
@ -327,11 +378,17 @@ const Navbar = ({
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="signinBtnNavbar">
|
<div className="signinBtnNavbar">
|
||||||
|
<div onClick={handleDemoModal}>Book Demo</div>
|
||||||
<div onClick={handleNavigateStore}>
|
<div onClick={handleNavigateStore}>
|
||||||
<sub style={{ fontSize: "14px" }}>Store</sub>
|
<sub style={{ fontSize: "14px" }}>Store</sub>
|
||||||
<sup>BETA</sup>
|
<sup>BETA</sup>
|
||||||
</div>
|
</div>
|
||||||
<div onClick={handleDemoModal}>Get Demo</div>
|
<div
|
||||||
|
onClick={() => window.open("https://wa.me/917324000012", "_blank")}
|
||||||
|
style={{ cursor: "pointer", display: "flex", alignItems: "center", gap: "0.5rem" }}
|
||||||
|
>
|
||||||
|
<FaWhatsapp style={{ fontSize: "20px" }} />
|
||||||
|
</div>
|
||||||
{!userId ? (
|
{!userId ? (
|
||||||
<button onClick={handleSiginOnclick}>
|
<button onClick={handleSiginOnclick}>
|
||||||
Sign in
|
Sign in
|
||||||
|
|
@ -411,9 +468,42 @@ const Navbar = ({
|
||||||
className={`NavbarMenuResponsive ${closingMenu ? "closing" : ""}`}
|
className={`NavbarMenuResponsive ${closingMenu ? "closing" : ""}`}
|
||||||
>
|
>
|
||||||
<div className="ResnavbarOption">
|
<div className="ResnavbarOption">
|
||||||
|
<span onClick={navigateAndScrollToTop} className="indusOpen">
|
||||||
|
Home
|
||||||
|
</span>
|
||||||
|
<span onClick={handleSolutionsRes} className="indusOpen">
|
||||||
|
Solutions{" "}
|
||||||
|
{solutionsOpenRes ? (
|
||||||
|
<FaChevronUp size={10} />
|
||||||
|
) : (
|
||||||
|
<FaChevronDown size={10} />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
{solutionsOpenRes && (
|
||||||
|
<div className="solutions-dropdown-mobile">
|
||||||
|
<div className="solution-item-mobile" onClick={() => navigate(`${subDirectory}solutions/retail-billing`)}>
|
||||||
|
Retail Billing
|
||||||
|
</div>
|
||||||
|
<div className="solution-item-mobile" onClick={() => navigate(`${subDirectory}solutions/inventory-purchase`)}>
|
||||||
|
Inventory & Purchase
|
||||||
|
</div>
|
||||||
|
<div className="solution-item-mobile" onClick={() => navigate(`${subDirectory}solutions/weighing-scale-pos`)}>
|
||||||
|
Weighing Scale POS
|
||||||
|
</div>
|
||||||
|
<div className="solution-item-mobile" onClick={() => navigate(`${subDirectory}solutions/multi-store-erp`)}>
|
||||||
|
Multi-Store ERP
|
||||||
|
</div>
|
||||||
|
<div className="solution-item-mobile" onClick={() => navigate(`${subDirectory}solutions/gst-billing-e-invoice`)}>
|
||||||
|
GST Billing & E-Invoice
|
||||||
|
</div>
|
||||||
|
<div className="solution-item-mobile" onClick={() => navigate(`${subDirectory}solutions/offline-billing`)}>
|
||||||
|
Offline Billing
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<span onClick={handleIndustryRes} className="indusOpen">
|
<span onClick={handleIndustryRes} className="indusOpen">
|
||||||
Industries{" "}
|
Industries{" "}
|
||||||
{industry ? (
|
{industryRes ? (
|
||||||
<FaChevronUp size={10} />
|
<FaChevronUp size={10} />
|
||||||
) : (
|
) : (
|
||||||
<FaChevronDown size={10} />
|
<FaChevronDown size={10} />
|
||||||
|
|
@ -428,9 +518,6 @@ const Navbar = ({
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{/* <span onClick={scrollToSection} className="indusOpen">
|
|
||||||
Offerings
|
|
||||||
</span> */}
|
|
||||||
<span className="indusOpen" onClick={handleCompanyListRes}>
|
<span className="indusOpen" onClick={handleCompanyListRes}>
|
||||||
Company <FaChevronDown size={10} />
|
Company <FaChevronDown size={10} />
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -438,31 +525,36 @@ const Navbar = ({
|
||||||
<div className="industryRes">
|
<div className="industryRes">
|
||||||
<div className="compnayListsRes">
|
<div className="compnayListsRes">
|
||||||
<p onClick={handleAboutUs}>About Us</p>
|
<p onClick={handleAboutUs}>About Us</p>
|
||||||
{/* <p>Partnership</p>
|
|
||||||
<p>Events</p> */}
|
|
||||||
{/* <p>Webinars</p> */}
|
|
||||||
<p onClick={handleNavigatePrivacy}>Privacy Policy </p>
|
<p onClick={handleNavigatePrivacy}>Privacy Policy </p>
|
||||||
<p onClick={handleNavigatetestimonials}>Testimonials </p>
|
<p onClick={handleNavigatetestimonials}>Testimonials </p>
|
||||||
{/* <p>Terms </p> */}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<span onClick={handleBlogPage} className="indusOpen">
|
|
||||||
Blog{" "}
|
|
||||||
</span>
|
|
||||||
<span onClick={handlePricing} className="indusOpen">
|
<span onClick={handlePricing} className="indusOpen">
|
||||||
Pricing{" "}
|
Pricing
|
||||||
|
</span>
|
||||||
|
<span onClick={handleBlogPage} className="indusOpen">
|
||||||
|
Blog
|
||||||
|
</span>
|
||||||
|
<span onClick={() => navigate(`${subDirectory}case-studies`)} className="indusOpen">
|
||||||
|
Case Studies
|
||||||
</span>
|
</span>
|
||||||
<span onClick={handleNavigateContact} className="indusOpen">
|
<span onClick={handleNavigateContact} className="indusOpen">
|
||||||
Contact Us{" "}
|
Contact Us
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="signinBtnNavbarRes">
|
<div className="signinBtnNavbarRes">
|
||||||
|
<div onClick={handleDemoModal}>Book Demo</div>
|
||||||
<div onClick={handleNavigateStore}>
|
<div onClick={handleNavigateStore}>
|
||||||
<sub style={{ fontSize: "14px" }}>Store</sub>
|
<sub style={{ fontSize: "14px" }}>Store</sub>
|
||||||
<sup>BETA</sup>
|
<sup>BETA</sup>
|
||||||
</div>
|
</div>
|
||||||
<div onClick={handleDemoModal}>Get Demo</div>
|
<div
|
||||||
|
onClick={() => window.open("https://wa.me/917324000012", "_blank")}
|
||||||
|
style={{ cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", gap: "0.5rem" }}
|
||||||
|
>
|
||||||
|
<FaWhatsapp style={{ fontSize: "20px" }} />
|
||||||
|
</div>
|
||||||
<button onClick={handleSiginOnclick}>
|
<button onClick={handleSiginOnclick}>
|
||||||
<div></div>
|
<div></div>
|
||||||
Sign in
|
Sign in
|
||||||
|
|
@ -476,6 +568,19 @@ const Navbar = ({
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Sticky Footer for Book Demo & WhatsApp */}
|
||||||
|
<div className="mobile-sticky-footer">
|
||||||
|
<div onClick={handleDemoModal} className="mobile-sticky-btn">
|
||||||
|
Book Demo
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
onClick={() => window.open("https://wa.me/917324000012", "_blank")}
|
||||||
|
className="mobile-sticky-btn whatsapp-btn"
|
||||||
|
>
|
||||||
|
<FaWhatsapp style={{ fontSize: "20px" }} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ import Innovation from "../Images/Innovation.webp";
|
||||||
import OverViewVideo from "../Videos/OverView.webm";
|
import OverViewVideo from "../Videos/OverView.webm";
|
||||||
import AnimatedText from "./AnimatedText/AnimatedText";
|
import AnimatedText from "./AnimatedText/AnimatedText";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
import { getAdminPanel } from "../../features/AdminPanel/AdminPanel";
|
||||||
|
|
||||||
const subDirectory = import.meta.env.BASE_URL;
|
const subDirectory = import.meta.env.BASE_URL;
|
||||||
gsap.registerPlugin(ScrollTrigger, SplitText);
|
gsap.registerPlugin(ScrollTrigger, SplitText);
|
||||||
|
|
@ -22,27 +24,97 @@ const OverView = ({
|
||||||
handleModalSignInClose,
|
handleModalSignInClose,
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const dispatch = useDispatch();
|
||||||
const sloganRef = useRef(null);
|
const sloganRef = useRef(null);
|
||||||
const featuresRef = useRef([]);
|
const featuresRef = useRef([]);
|
||||||
const aiCardRef = useRef(null);
|
const aiCardRef = useRef(null);
|
||||||
|
|
||||||
const features = [
|
// 🚀 Dynamic content from CMS
|
||||||
|
const [heroContent, setHeroContent] = useState({
|
||||||
|
mainHeadline: "Retail ERP & POS built for Indian MSMEs — fast billing, smart inventory, GST-ready.",
|
||||||
|
description: "A SaaS platform that empowers Small and Medium Businesses by digitizing operations and reducing Total Cost of Ownership with minimal investment.",
|
||||||
|
ctaButtonText: "Experience Now",
|
||||||
|
ctaButtonLink: "/signin"
|
||||||
|
});
|
||||||
|
|
||||||
|
const [offeringsContent, setOfferingsContent] = useState([
|
||||||
{
|
{
|
||||||
|
id: 1,
|
||||||
icon: Experience,
|
icon: Experience,
|
||||||
title: "Experience",
|
title: "Experience",
|
||||||
desc: "Proven expertise delivering real value",
|
desc: "Proven expertise delivering real value",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: 2,
|
||||||
icon: Innovation,
|
icon: Innovation,
|
||||||
title: "Innovation",
|
title: "Innovation",
|
||||||
desc: "Smarter intelligence for better outcomes",
|
desc: "Smarter intelligence for better outcomes",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: 3,
|
||||||
icon: CostEfficiency,
|
icon: CostEfficiency,
|
||||||
title: "Cost Efficiency",
|
title: "Cost Efficiency",
|
||||||
desc: "Maximum value with minimal cost",
|
desc: "Maximum value with minimal cost",
|
||||||
},
|
},
|
||||||
];
|
]);
|
||||||
|
|
||||||
|
// Fetch dynamic content from CMS
|
||||||
|
useEffect(() => {
|
||||||
|
fetchHeroContent();
|
||||||
|
fetchOfferingsContent();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchHeroContent = async () => {
|
||||||
|
try {
|
||||||
|
const res = await dispatch(
|
||||||
|
getAdminPanel({ sectionName: "HeroSection" })
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
if (res?.data?.statusCode === 1 && res?.data?.data?.length > 0) {
|
||||||
|
const heroData = res.data.data[0];
|
||||||
|
if (heroData.Content) {
|
||||||
|
const content = JSON.parse(heroData.Content);
|
||||||
|
setHeroContent({
|
||||||
|
mainHeadline: content.mainHeadline || heroContent.mainHeadline,
|
||||||
|
description: content.description || heroContent.description,
|
||||||
|
ctaButtonText: content.ctaButtonText || heroContent.ctaButtonText,
|
||||||
|
ctaButtonLink: content.ctaButtonLink || heroContent.ctaButtonLink
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Using default hero content");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchOfferingsContent = async () => {
|
||||||
|
try {
|
||||||
|
const res = await dispatch(
|
||||||
|
getAdminPanel({ sectionName: "Offerings" })
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
if (res?.data?.statusCode === 1 && res?.data?.data?.length > 0) {
|
||||||
|
const offeringsData = res.data.data[0];
|
||||||
|
if (offeringsData.Content) {
|
||||||
|
const content = JSON.parse(offeringsData.Content);
|
||||||
|
if (content.offerings && content.offerings.length > 0) {
|
||||||
|
// Map with icons
|
||||||
|
const mappedOfferings = content.offerings.map(offering => ({
|
||||||
|
...offering,
|
||||||
|
icon: offering.icon === 'experience' ? Experience :
|
||||||
|
offering.icon === 'innovation' ? Innovation :
|
||||||
|
offering.icon === 'cost' ? CostEfficiency : Experience
|
||||||
|
}));
|
||||||
|
setOfferingsContent(mappedOfferings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Using default offerings content");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const features = offeringsContent;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Slogan animation with SplitText
|
// Slogan animation with SplitText
|
||||||
|
|
@ -114,18 +186,30 @@ const OverView = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="OverView-Master">
|
<div className="OverView-Master">
|
||||||
{/* Background Video */}
|
{/* Background Video - Optimized loading */}
|
||||||
<video autoPlay muted loop playsInline className="bg-video">
|
<video
|
||||||
<source src={OverViewVideo} type="video/mp4" preload="metadata" />
|
autoPlay
|
||||||
|
muted
|
||||||
|
loop
|
||||||
|
playsInline
|
||||||
|
className="bg-video"
|
||||||
|
preload="none"
|
||||||
|
loading="lazy"
|
||||||
|
>
|
||||||
|
<source src={OverViewVideo} type="video/webm" />
|
||||||
{/* <source src="https://csjnrlpkmurliskqkmnp.supabase.co/storage/v1/object/public/Store/PozoAppBg3.mp4" type="video/mp4" /> */}
|
{/* <source src="https://csjnrlpkmurliskqkmnp.supabase.co/storage/v1/object/public/Store/PozoAppBg3.mp4" type="video/mp4" /> */}
|
||||||
</video>
|
</video>
|
||||||
{/* Navbar */}
|
{/* Navbar */}
|
||||||
{/* <Navbar /> */}
|
{/* <Navbar /> */}
|
||||||
|
|
||||||
{/* Slogan */}
|
{/* Slogan - Dynamic from CMS */}
|
||||||
<div className="overviewSlogan" ref={sloganRef}>
|
<div className="overviewSlogan" ref={sloganRef}>
|
||||||
Streamline... Simplify... <br />
|
{heroContent.mainHeadline.split('\n').map((line, i) => (
|
||||||
Succeed with Pozo Apps
|
<React.Fragment key={i}>
|
||||||
|
{line}
|
||||||
|
{i < heroContent.mainHeadline.split('\n').length - 1 && <br />}
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
|
|
@ -138,7 +222,7 @@ const OverView = ({
|
||||||
className="feature-item"
|
className="feature-item"
|
||||||
ref={(el) => (featuresRef.current[index] = el)}
|
ref={(el) => (featuresRef.current[index] = el)}
|
||||||
>
|
>
|
||||||
<img src={item.icon} alt={item.title} width={40} />
|
<img src={item.icon} alt={item.title} width={40} loading="lazy" />
|
||||||
<div className="feature-text">
|
<div className="feature-text">
|
||||||
<h3>{item.title}</h3>
|
<h3>{item.title}</h3>
|
||||||
<p>{item.desc}</p>
|
<p>{item.desc}</p>
|
||||||
|
|
@ -151,14 +235,13 @@ const OverView = ({
|
||||||
<div className="hero-right">
|
<div className="hero-right">
|
||||||
<div className="ai-card">
|
<div className="ai-card">
|
||||||
<p>
|
<p>
|
||||||
Agentic AI-powered SaaS solutions for businesses of all sizes –
|
{heroContent.description}
|
||||||
from MSME to Enterprises.
|
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
className="experience-btn"
|
className="experience-btn"
|
||||||
onClick={() => navigate(`${subDirectory}signin`)}
|
onClick={() => navigate(`${subDirectory}${heroContent.ctaButtonLink.replace(/^\//, '')}`)}
|
||||||
>
|
>
|
||||||
Experience Now
|
{heroContent.ctaButtonText}
|
||||||
<div className="icon-container">
|
<div className="icon-container">
|
||||||
<HiMiniArrowUpRight className="icon-main" />
|
<HiMiniArrowUpRight className="icon-main" />
|
||||||
<HiMiniArrowUpRight className="icon-hover" />
|
<HiMiniArrowUpRight className="icon-hover" />
|
||||||
|
|
|
||||||
|
|
@ -666,6 +666,15 @@ const PricingPozoApp = () => {
|
||||||
if (industry) {
|
if (industry) {
|
||||||
handleIndustry();
|
handleIndustry();
|
||||||
}
|
}
|
||||||
|
// Clean URL: Remove special chars, convert spaces to hyphens
|
||||||
|
const cleanUrl = AppName
|
||||||
|
.replace(/[,]/g, '') // Remove commas
|
||||||
|
.replace(/\s+/g, '-') // Spaces to hyphens
|
||||||
|
.replace(/&/g, 'and') // & to 'and'
|
||||||
|
.replace(/[^a-z0-9-]/gi, '') // Remove other special chars
|
||||||
|
.toLowerCase();
|
||||||
|
navigate(`${subDirectory}${cleanUrl}`);
|
||||||
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Moved loading check after all hooks
|
// Moved loading check after all hooks
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ const ResponsiveApp = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePricing = () => {
|
const handlePricing = () => {
|
||||||
navigate(`${subDirectory}pricing-pozoapp`);
|
navigate(`${subDirectory}pricing`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNavigateStore = () => {
|
const handleNavigateStore = () => {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import React, { useState, useEffect, useRef } from "react";
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
import "../Styles/SignIn.scss";
|
import "../Styles/SignIn.scss";
|
||||||
import pozominilogoWhite from "../Images/pozominilogoWhite.webp";
|
import pozoAppLogo from "../Images/pozoAppLogo.webp";
|
||||||
import pozoAppLogo from "../Images/pozoAppLogo.webp";
|
|
||||||
import { RiArrowRightUpLine } from "react-icons/ri";
|
import { RiArrowRightUpLine } from "react-icons/ri";
|
||||||
import { FaChevronDown } from "react-icons/fa";
|
import { FaChevronDown } from "react-icons/fa";
|
||||||
import { useNavigate, useLocation } from "react-router-dom";
|
import { useNavigate, useLocation } from "react-router-dom";
|
||||||
|
|
@ -719,7 +718,7 @@ const SignIn = () => {
|
||||||
<div className="inputsTitle">
|
<div className="inputsTitle">
|
||||||
<img
|
<img
|
||||||
className="whitelogoPng"
|
className="whitelogoPng"
|
||||||
src={pozominilogoWhite}
|
src={pozoAppLogo}
|
||||||
alt=""
|
alt=""
|
||||||
onClick={navigateHomePage}
|
onClick={navigateHomePage}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import React from "react";
|
||||||
|
import Navbar from "../Components/Navbar";
|
||||||
|
import Footer from "../Components/Footer";
|
||||||
|
import "./CaseStudies.scss";
|
||||||
|
|
||||||
|
const CaseStudies = () => {
|
||||||
|
return (
|
||||||
|
<div className="case-studies-page">
|
||||||
|
<Navbar isScrolled={true} forceTopZero={true} />
|
||||||
|
|
||||||
|
<div className="case-studies-hero">
|
||||||
|
<div className="case-studies-hero-content">
|
||||||
|
<h1>Case Studies</h1>
|
||||||
|
<p>Success stories from businesses powered by PozoApp</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="case-studies-container">
|
||||||
|
<div className="coming-soon-message">
|
||||||
|
<h2>Coming Soon</h2>
|
||||||
|
<p>We're currently working on bringing you inspiring success stories from our clients.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CaseStudies;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
.case-studies-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #000;
|
||||||
|
color: #fff;
|
||||||
|
font-family: "NeueMontreal", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.case-studies-hero {
|
||||||
|
padding: 120px 2rem 80px;
|
||||||
|
text-align: center;
|
||||||
|
background: linear-gradient(135deg, #000 0%, #1a1a1a 100%);
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 100px 1.5rem 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.case-studies-hero-content {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 56px;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0 0 1.5rem 0;
|
||||||
|
background: linear-gradient(135deg, #fff 0%, #999 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
font-size: 36px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 22px;
|
||||||
|
color: #999;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.case-studies-container {
|
||||||
|
padding: 120px 2rem;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 80px 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coming-soon-message {
|
||||||
|
h2 {
|
||||||
|
font-size: 48px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0 0 1.5rem 0;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #999;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,20 +1,9 @@
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState, lazy, Suspense } from "react";
|
||||||
import Lenis from "@studio-freight/lenis";
|
import Lenis from "@studio-freight/lenis";
|
||||||
import { gsap } from "gsap";
|
import { gsap } from "gsap";
|
||||||
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||||
import "./HomePage.scss";
|
import "./HomePage.scss";
|
||||||
import { IoClose } from "react-icons/io5";
|
import { IoClose } from "react-icons/io5";
|
||||||
import OverView from "../Components/OverView.jsx";
|
|
||||||
import Offering from "../Components/Offering.jsx";
|
|
||||||
import DigitalSection from "../Components/DigitalSection.jsx";
|
|
||||||
import Footer from "../Components/Footer.jsx";
|
|
||||||
import NoLimt from "../Components/NoLimt.jsx";
|
|
||||||
import TrendingApp from "../Components/TrendingApp.jsx";
|
|
||||||
import FaqSection from "../Components/FaqSection.jsx";
|
|
||||||
import Insiders from "../Components/Insiders.jsx";
|
|
||||||
import Industries from "../Components/Industries.jsx";
|
|
||||||
import PozoVideo from "../Components/PozoVideo.jsx";
|
|
||||||
import Loader from "../Components/Loader/PozoLoader.jsx";
|
|
||||||
import { FaWhatsapp } from "react-icons/fa";
|
import { FaWhatsapp } from "react-icons/fa";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { FaChevronUp } from "react-icons/fa";
|
import { FaChevronUp } from "react-icons/fa";
|
||||||
|
|
@ -27,15 +16,30 @@ import {
|
||||||
getAllApplicationData,
|
getAllApplicationData,
|
||||||
} from "../../features/publicHome/publicHome";
|
} from "../../features/publicHome/publicHome";
|
||||||
import { getSession, sessionStore } from "../../Services/others";
|
import { getSession, sessionStore } from "../../Services/others";
|
||||||
import Navbar from "../Components/Navbar.jsx";
|
import { getSeo } from "../../features/SEO/seo.js";
|
||||||
import IndustriesList from "../Components/IndustriesList.jsx";
|
|
||||||
import CompanyList from "../Components/companyList.jsx";
|
|
||||||
import BookDemo from "../Components/BookDemo.jsx";
|
|
||||||
import ModalSignIn from "../Components/ModalSignIn.jsx";
|
|
||||||
import SEO from "../../Components/SEO/SEO.jsx";
|
|
||||||
import { getSeo } from "../../features/SEO/seo.js"; // assume this exists
|
|
||||||
import { getConfigNames } from "../../features/configmasterPage/configmasterPage.js";
|
import { getConfigNames } from "../../features/configmasterPage/configmasterPage.js";
|
||||||
|
|
||||||
|
// ✅ Critical imports - Load immediately
|
||||||
|
import Navbar from "../Components/Navbar.jsx";
|
||||||
|
import OverView from "../Components/OverView.jsx";
|
||||||
|
import Loader from "../Components/Loader/PozoLoader.jsx";
|
||||||
|
import SEO from "../../Components/SEO/SEO.jsx";
|
||||||
|
|
||||||
|
// 🚀 Lazy imports - Code split for better performance
|
||||||
|
const Offering = lazy(() => import("../Components/Offering.jsx"));
|
||||||
|
const DigitalSection = lazy(() => import("../Components/DigitalSection.jsx"));
|
||||||
|
const PozoVideo = lazy(() => import("../Components/PozoVideo.jsx"));
|
||||||
|
const TrendingApp = lazy(() => import("../Components/TrendingApp.jsx"));
|
||||||
|
const FaqSection = lazy(() => import("../Components/FaqSection.jsx"));
|
||||||
|
const Insiders = lazy(() => import("../Components/Insiders.jsx"));
|
||||||
|
const Footer = lazy(() => import("../Components/Footer.jsx"));
|
||||||
|
|
||||||
|
// 🎯 Conditional lazy imports - Load only when needed
|
||||||
|
const IndustriesList = lazy(() => import("../Components/IndustriesList.jsx"));
|
||||||
|
const CompanyList = lazy(() => import("../Components/companyList.jsx"));
|
||||||
|
const BookDemo = lazy(() => import("../Components/BookDemo.jsx"));
|
||||||
|
const ModalSignIn = lazy(() => import("../Components/ModalSignIn.jsx"));
|
||||||
|
|
||||||
// import og from "../../../public/og/home.jpg"
|
// import og from "../../../public/og/home.jpg"
|
||||||
|
|
||||||
const subDirectory = import.meta.env.BASE_URL;
|
const subDirectory = import.meta.env.BASE_URL;
|
||||||
|
|
@ -66,68 +70,63 @@ const HomePage = () => {
|
||||||
const [seoData, setSeoData] = useState(null);
|
const [seoData, setSeoData] = useState(null);
|
||||||
const [allpagesData, setAllpagesData] = useState([]);
|
const [allpagesData, setAllpagesData] = useState([]);
|
||||||
|
|
||||||
|
// 🚀 Optimized: All independent API calls run in parallel
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchSEOData = async () => {
|
const initializeData = async () => {
|
||||||
try {
|
try {
|
||||||
// Get all pages
|
// Run all independent API calls in parallel!
|
||||||
const Res = await dispatch(
|
const [seoConfigRes, appDataRes, tokenRes] = await Promise.all([
|
||||||
getConfigNames({ TypeName: "SEO" })
|
// SEO Config
|
||||||
).unwrap();
|
dispatch(getConfigNames({ TypeName: "SEO" })).unwrap(),
|
||||||
if (Res?.data?.statusCode === 1) {
|
// App Data
|
||||||
const pages = Res.data.data;
|
dispatch(getAllApplicationData()).unwrap(),
|
||||||
|
// Token
|
||||||
|
dispatch(PostToken({ username: "1000000001", password: "1234" })).unwrap()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Process SEO data
|
||||||
|
if (seoConfigRes?.data?.statusCode === 1) {
|
||||||
|
const pages = seoConfigRes.data.data;
|
||||||
setAllpagesData(pages);
|
setAllpagesData(pages);
|
||||||
|
|
||||||
// Find Home page ID
|
|
||||||
const SeoId = pages.find((e) => e.ConfigName === "home")?.ConfigId;
|
const SeoId = pages.find((e) => e.ConfigName === "home")?.ConfigId;
|
||||||
if (!SeoId) {
|
if (SeoId) {
|
||||||
console.warn("Home page ConfigId not found");
|
// Fetch SEO details (non-blocking)
|
||||||
return;
|
dispatch(getSeo({ PageId: SeoId })).unwrap().then((response) => {
|
||||||
}
|
if (response?.data?.statusCode === 1) {
|
||||||
|
const data = response.data.data.find((e) => e.PageId === SeoId);
|
||||||
// Fetch SEO for Home page
|
if (data) {
|
||||||
const response = await dispatch(getSeo({ PageId: SeoId })).unwrap();
|
setSeoData({
|
||||||
if (response?.data?.statusCode === 1) {
|
metaTitle: data?.MetaTitle,
|
||||||
const data = response.data.data.find((e) => e.PageId === SeoId);
|
metaDescription: data?.MetaDesc,
|
||||||
if (data) {
|
keywords: data?.Keywords,
|
||||||
setSeoData({
|
imageAltText: data?.ImgAltText,
|
||||||
metaTitle: data?.MetaTitle,
|
});
|
||||||
metaDescription: data?.MetaDesc,
|
}
|
||||||
keywords: data?.Keywords,
|
}
|
||||||
imageAltText: data?.ImgAltText,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process App data
|
||||||
|
if (appDataRes?.data?.statusCode === 1) {
|
||||||
|
const activeApps = appDataRes?.data?.data?.filter(
|
||||||
|
(value) => value?.ActiveStatus === "A"
|
||||||
|
);
|
||||||
|
setAppCategory(activeApps);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching SEO data:", error);
|
console.error("Error initializing data:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchSEOData();
|
initializeData();
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getAppData();
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const getAppData = async () => {
|
|
||||||
try {
|
|
||||||
const response = await dispatch(getAllApplicationData()).unwrap();
|
|
||||||
if (response?.data?.statusCode === 1) {
|
|
||||||
let finalsubCategory = response?.data?.data?.filter(
|
|
||||||
(value) => value?.ActiveStatus === "A"
|
|
||||||
);
|
|
||||||
setAppCategory(finalsubCategory);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching app data:", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
console.log(AppCategory, "AppCategory");
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Simulate loading delay
|
// Show page immediately - don't wait!
|
||||||
const timer = setTimeout(() => setLoading(false), 100);
|
const timer = setTimeout(() => setLoading(false), 300);
|
||||||
|
|
||||||
// Lenis smooth scrolling
|
// Lenis smooth scrolling
|
||||||
const lenisInstance = new Lenis({
|
const lenisInstance = new Lenis({
|
||||||
|
|
@ -159,55 +158,44 @@ const HomePage = () => {
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Separate useEffect for API calls
|
// 🚀 Optimized: Fetch categories in parallel with other data (if needed for navbar)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchConfigName = async () => {
|
const fetchCategoryData = async () => {
|
||||||
setSubCategory([]);
|
|
||||||
setAppCategory([]);
|
|
||||||
const response = await dispatch(getCategoryData()).unwrap();
|
|
||||||
if (response?.data?.statusCode === 1) {
|
|
||||||
let finalCategory = response?.data?.data;
|
|
||||||
setCategory(finalCategory);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const Tokens = async () => {
|
|
||||||
let data = {
|
|
||||||
username: "1000000001",
|
|
||||||
password: "1234",
|
|
||||||
};
|
|
||||||
try {
|
try {
|
||||||
await dispatch(PostToken(data)).unwrap();
|
const response = await dispatch(getCategoryData()).unwrap();
|
||||||
|
if (response?.data?.statusCode === 1) {
|
||||||
|
const finalCategory = response?.data?.data;
|
||||||
|
setCategory(finalCategory);
|
||||||
|
|
||||||
|
// Auto-fetch first subcategory (non-blocking)
|
||||||
|
if (finalCategory?.[0]?.CateId) {
|
||||||
|
dispatch(getSubCategoryData(finalCategory[0].CateId)).unwrap()
|
||||||
|
.then((subRes) => {
|
||||||
|
if (subRes?.data?.statusCode === 1) {
|
||||||
|
const activeSubCat = subRes?.data?.data?.filter(
|
||||||
|
(value) => value.ActiveStatus === "A"
|
||||||
|
);
|
||||||
|
setSubCategory(activeSubCat);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => console.error("Error fetching subcategory:", err));
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching token:", error);
|
console.error("Error fetching categories:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const initializeData = async () => {
|
// Only fetch if needed for navbar/menu
|
||||||
await fetchConfigName();
|
if (AppCategory.length > 0) {
|
||||||
await Tokens();
|
// Already have app data, skip category fetch
|
||||||
};
|
} else {
|
||||||
initializeData();
|
fetchCategoryData();
|
||||||
}, []);
|
|
||||||
// Auto-fetch subcategories when categories load
|
|
||||||
useEffect(() => {
|
|
||||||
const getSubCategory = async (cateId) => {
|
|
||||||
// setAppCategory([]);
|
|
||||||
const response = await dispatch(getSubCategoryData(cateId)).unwrap();
|
|
||||||
if (response?.data?.statusCode === 1) {
|
|
||||||
let finalsubCategory = response?.data?.data?.filter(
|
|
||||||
(value) => value.ActiveStatus === "A"
|
|
||||||
);
|
|
||||||
setSubCategory(finalsubCategory);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (Category?.[0]?.CateId != undefined) {
|
|
||||||
getSubCategory(Category?.[0]?.CateId);
|
|
||||||
}
|
}
|
||||||
}, [Category]);
|
}, [AppCategory]);
|
||||||
|
|
||||||
// Auto-fetch apps when subcategories load
|
// Auto-fetch apps when subcategories load
|
||||||
|
// Commented out - not needed with getAllApplicationData
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// const getAppData = async (subcatId) => {
|
// const getAppData = async (subcatId) => {
|
||||||
// const response = await dispatch(getApplicationData(subcatId)).unwrap();
|
// const response = await dispatch(getApplicationData(subcatId)).unwrap();
|
||||||
|
|
@ -224,8 +212,6 @@ const HomePage = () => {
|
||||||
// }
|
// }
|
||||||
// }, [SubCategory]);
|
// }, [SubCategory]);
|
||||||
|
|
||||||
if (loading) return <Loader />;
|
|
||||||
|
|
||||||
const scrollToTop = () => {
|
const scrollToTop = () => {
|
||||||
if (lenis) {
|
if (lenis) {
|
||||||
lenis.scrollTo(0, { duration: 1.5 });
|
lenis.scrollTo(0, { duration: 1.5 });
|
||||||
|
|
@ -235,7 +221,16 @@ const HomePage = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const redirectApp = async (AppName, AppId) => {
|
const redirectApp = async (AppName, AppId) => {
|
||||||
navigate(`${subDirectory}${AppName}`);
|
sessionStore("AppId", AppId);
|
||||||
|
sessionStore("AppName", AppName);
|
||||||
|
// Clean URL: Remove special chars, convert spaces to hyphens
|
||||||
|
const cleanUrl = AppName
|
||||||
|
.replace(/[,]/g, '') // Remove commas
|
||||||
|
.replace(/\s+/g, '-') // Spaces to hyphens
|
||||||
|
.replace(/&/g, 'and') // & to 'and'
|
||||||
|
.replace(/[^a-z0-9-]/gi, '') // Remove other special chars
|
||||||
|
.toLowerCase();
|
||||||
|
navigate(`${subDirectory}${cleanUrl}`);
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -329,32 +324,30 @@ const HomePage = () => {
|
||||||
handleModalSignInClose={handleModalSignInClose}
|
handleModalSignInClose={handleModalSignInClose}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
|
||||||
<Offering />
|
<Suspense fallback={null}>
|
||||||
</section>
|
<section>
|
||||||
<section>
|
<Offering />
|
||||||
<DigitalSection />
|
</section>
|
||||||
</section>
|
<section>
|
||||||
<section>
|
<DigitalSection />
|
||||||
<PozoVideo />
|
</section>
|
||||||
</section>
|
<section>
|
||||||
|
<PozoVideo />
|
||||||
{/* Application DropDown */}
|
</section>
|
||||||
{/* <section>
|
<section>
|
||||||
<Industries />
|
<TrendingApp />
|
||||||
</section> */}
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<TrendingApp />
|
<FaqSection />
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<FaqSection />
|
<Insiders />
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<Insiders />
|
<Footer AppCategory={AppCategory} />
|
||||||
</section>
|
</section>
|
||||||
<section>
|
</Suspense>
|
||||||
<Footer />
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="folatingWhatsapp"
|
className="folatingWhatsapp"
|
||||||
|
|
@ -371,24 +364,36 @@ const HomePage = () => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{industry && (
|
{industry && (
|
||||||
<IndustriesList
|
<Suspense fallback={null}>
|
||||||
industryRef={industryRef}
|
<IndustriesList
|
||||||
closingIndustry={closingIndustry}
|
industryRef={industryRef}
|
||||||
AppCategory={AppCategory}
|
closingIndustry={closingIndustry}
|
||||||
redirectApp={redirectApp}
|
AppCategory={AppCategory}
|
||||||
/>
|
redirectApp={redirectApp}
|
||||||
|
/>
|
||||||
|
</Suspense>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{company && (
|
{company && (
|
||||||
<CompanyList
|
<Suspense fallback={null}>
|
||||||
companyRef={companyRef}
|
<CompanyList
|
||||||
closingCompany={closingCompany}
|
companyRef={companyRef}
|
||||||
/>
|
closingCompany={closingCompany}
|
||||||
|
/>
|
||||||
|
</Suspense>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{demoModal && <BookDemo onClose={handleDemoModalClose} />}
|
{demoModal && (
|
||||||
|
<Suspense fallback={null}>
|
||||||
|
<BookDemo onClose={handleDemoModalClose} />
|
||||||
|
</Suspense>
|
||||||
|
)}
|
||||||
|
|
||||||
{modalSignIn && <ModalSignIn onClose={handleModalSignInClose} />}
|
{modalSignIn && (
|
||||||
|
<Suspense fallback={null}>
|
||||||
|
<ModalSignIn onClose={handleModalSignInClose} />
|
||||||
|
</Suspense>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
import React from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import "./Solutions.scss";
|
||||||
|
import Navbar from "../Components/Navbar";
|
||||||
|
import Footer from "../Components/Footer";
|
||||||
|
|
||||||
|
const subDirectory = import.meta.env.BASE_URL;
|
||||||
|
|
||||||
|
const Solutions = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const solutions = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "Retail Billing",
|
||||||
|
description: "Fast, intuitive billing system for retail stores with GST compliance",
|
||||||
|
icon: "🛒",
|
||||||
|
path: "retail-billing",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "Inventory & Purchase",
|
||||||
|
description: "Smart inventory management with real-time stock tracking",
|
||||||
|
icon: "📦",
|
||||||
|
path: "inventory-purchase",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: "Weighing Scale POS",
|
||||||
|
description: "Integrated weighing scale with POS for seamless billing",
|
||||||
|
icon: "⚖️",
|
||||||
|
path: "weighing-scale-pos",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: "Multi-Store ERP",
|
||||||
|
description: "Manage multiple stores from one centralized platform",
|
||||||
|
icon: "🏪",
|
||||||
|
path: "multi-store-erp",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
title: "GST Billing & E-Invoice",
|
||||||
|
description: "GST-ready billing with automated e-invoice generation",
|
||||||
|
icon: "📄",
|
||||||
|
path: "gst-billing-e-invoice",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
title: "Offline Billing",
|
||||||
|
description: "Continue billing even without internet connectivity",
|
||||||
|
icon: "📴",
|
||||||
|
path: "offline-billing",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleSolutionClick = (path) => {
|
||||||
|
navigate(`${subDirectory}solutions/${path}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="solutions-page">
|
||||||
|
<Navbar isScrolled={true} forceTopZero={true} />
|
||||||
|
|
||||||
|
<div className="solutions-hero">
|
||||||
|
<div className="solutions-hero-content">
|
||||||
|
<h1>Our Solutions</h1>
|
||||||
|
<p>Comprehensive retail management solutions for Indian MSMEs</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="solutions-grid-container">
|
||||||
|
<div className="solutions-grid">
|
||||||
|
{solutions.map((solution) => (
|
||||||
|
<div
|
||||||
|
key={solution.id}
|
||||||
|
className="solution-card"
|
||||||
|
onClick={() => handleSolutionClick(solution.path)}
|
||||||
|
>
|
||||||
|
<div className="solution-icon">{solution.icon}</div>
|
||||||
|
<h3>{solution.title}</h3>
|
||||||
|
<p>{solution.description}</p>
|
||||||
|
<button className="solution-btn">
|
||||||
|
Learn More →
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Solutions;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
.solutions-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #000;
|
||||||
|
color: #fff;
|
||||||
|
font-family: "NeueMontreal", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solutions-hero {
|
||||||
|
padding: 120px 2rem 80px;
|
||||||
|
text-align: center;
|
||||||
|
background: linear-gradient(135deg, #000 0%, #1a1a1a 100%);
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 100px 1.5rem 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solutions-hero-content {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 56px;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0 0 1.5rem 0;
|
||||||
|
background: linear-gradient(135deg, #fff 0%, #999 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
font-size: 36px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 22px;
|
||||||
|
color: #999;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.solutions-grid-container {
|
||||||
|
padding: 80px 2rem 120px;
|
||||||
|
max-width: 1400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 60px 1.5rem 80px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.solutions-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||||
|
gap: 2rem;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card {
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 2.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
border-color: rgba(255, 255, 255, 0.2);
|
||||||
|
transform: translateY(-5px);
|
||||||
|
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-icon {
|
||||||
|
font-size: 48px;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #999;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0 0 1.5rem 0;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-btn {
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
color: #fff;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s;
|
||||||
|
font-family: inherit;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #fff;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,17 +1,24 @@
|
||||||
.Footer-Master {
|
.Footer-Master {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #010101;
|
background-color: #010101;
|
||||||
padding: 1.5rem 4rem 0 1.5rem;
|
// padding: 3rem 4rem 2rem 4rem;
|
||||||
|
padding: 2rem 1rem 1rem 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: flex-start;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 2rem;
|
gap: 4rem;
|
||||||
font-family: "NeueMontreal";
|
font-family: "NeueMontreal";
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
gap: 3rem;
|
||||||
|
padding: 2.5rem 2rem 2rem 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
padding: 1rem 1rem 1rem 1rem;
|
padding: 2rem 1.5rem 1.5rem 1.5rem;
|
||||||
|
gap: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerLeft {
|
.footerLeft {
|
||||||
|
|
@ -28,12 +35,13 @@
|
||||||
|
|
||||||
div {
|
div {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-size: 16px;
|
font-size: 23px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.clutter {
|
.clutter {
|
||||||
font-size: 16px;
|
font-size: 16px !important;
|
||||||
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
|
|
||||||
|
|
@ -70,53 +78,307 @@
|
||||||
color: #fff;
|
color: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 16px;
|
gap: 2rem;
|
||||||
flex-wrap: wrap;
|
flex: 1;
|
||||||
@media (max-width: 500px) {
|
max-width: 1000px;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-bottom: 3rem;
|
gap: 2rem;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerProducts {
|
.footerProducts {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 0;
|
||||||
column-gap: 2rem;
|
width: 100%;
|
||||||
|
max-width: 1100px;
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
// Top Bar - Everything in one line
|
||||||
grid-template-columns: repeat(2, 1fr);
|
.products-top-bar {
|
||||||
}
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
div {
|
@media (max-width: 900px) {
|
||||||
font-size: 18px;
|
flex-direction: column;
|
||||||
font-family: "NeueMontreal";
|
align-items: stretch;
|
||||||
font-weight: 400;
|
gap: 1rem;
|
||||||
grid-column: span 3;
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
grid-column: span 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
// Main "Products" heading
|
||||||
font-size: 13.5px;
|
.products-heading {
|
||||||
|
font-size: 18px;
|
||||||
font-family: "NeueMontreal";
|
font-family: "NeueMontreal";
|
||||||
font-weight: 400;
|
font-weight: 500;
|
||||||
cursor: pointer;
|
color: #fff;
|
||||||
transition: all 0.3s ease;
|
flex-shrink: 0;
|
||||||
|
|
||||||
&:hover {
|
@media (max-width: 900px) {
|
||||||
color: #418df7;
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search Box (in top bar)
|
||||||
|
.products-search-box {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
max-width: 350px;
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.products-search-icon {
|
||||||
|
position: absolute;
|
||||||
|
left: 16px;
|
||||||
|
font-size: 18px;
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.products-search-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 40px 10px 45px;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: #fff;
|
||||||
|
font-family: "NeueMontreal";
|
||||||
|
font-size: 14px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
background: rgba(255, 255, 255, 0.15);
|
||||||
|
border-color: #3588fd;
|
||||||
|
box-shadow: 0 0 0 3px rgba(53, 136, 253, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.products-search-clear {
|
||||||
|
position: absolute;
|
||||||
|
right: 12px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 18px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 4px 8px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
opacity: 0.6;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search Results Count
|
||||||
|
.products-search-results-count {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #888;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-family: "NeueMontreal";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search Results
|
||||||
|
.footer-search-results {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 0.5rem 2rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-item {
|
||||||
|
font-size: 14px;
|
||||||
|
font-family: "NeueMontreal";
|
||||||
|
font-weight: 400;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: rgba(53, 136, 253, 0.05);
|
||||||
|
border: 1px solid rgba(53, 136, 253, 0.1);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #3588fd;
|
||||||
|
background: rgba(53, 136, 253, 0.15);
|
||||||
|
border-color: rgba(53, 136, 253, 0.3);
|
||||||
|
transform: translateX(3px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No Results
|
||||||
|
.footer-no-results {
|
||||||
|
text-align: center;
|
||||||
|
padding: 2rem;
|
||||||
|
color: #888;
|
||||||
|
font-family: "NeueMontreal";
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
color: #888 !important;
|
||||||
|
cursor: default !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #888 !important;
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigation Controls (in top bar)
|
||||||
|
.footer-navigation {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.8rem;
|
||||||
|
margin-left: auto;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
margin-left: 0;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-nav-btn {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
color: #fff;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: 300;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: rgba(53, 136, 253, 0.2);
|
||||||
|
border-color: #3588fd;
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.3;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-page-indicator {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #888;
|
||||||
|
font-family: "NeueMontreal";
|
||||||
|
min-width: 60px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container for columns
|
||||||
|
.footer-columns-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 4rem;
|
||||||
|
// min-height: 300px;
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
gap: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Individual columns
|
||||||
|
.footer-column {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.2rem;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
|
// Category headers (Food & Beverages, Wellness, etc.)
|
||||||
|
.footer-category {
|
||||||
|
font-size: 11px;
|
||||||
|
font-family: "NeueMontreal";
|
||||||
|
font-weight: 500;
|
||||||
|
color: #888;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.8px;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Product links
|
||||||
|
p {
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: "NeueMontreal";
|
||||||
|
font-weight: 400;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
line-height: 1.9;
|
||||||
|
padding: 0px 0;
|
||||||
|
text-wrap: nowrap;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #3588fd;
|
||||||
|
transform: translateX(3px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
font-size: 13.5px;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerContact {
|
.footerContact {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
min-width: 100px;
|
||||||
|
|
||||||
div {
|
div {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-family: "NeueMontreal";
|
font-family: "NeueMontreal";
|
||||||
font-weight: 400;
|
font-weight: 500;
|
||||||
|
color: #fff;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
|
@ -126,10 +388,12 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.25s ease;
|
||||||
|
line-height: 1.8;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #418df7;
|
color: #3588fd;
|
||||||
|
transform: translateX(3px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -137,25 +401,31 @@
|
||||||
.footePhone {
|
.footePhone {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
gap: 0.5rem;
|
||||||
|
min-width: 100px;
|
||||||
|
|
||||||
div {
|
div {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-family: "NeueMontreal";
|
font-family: "NeueMontreal";
|
||||||
font-weight: 400;
|
font-weight: 500;
|
||||||
|
color: #fff;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
font-size: 13px;
|
font-size: 14px;
|
||||||
font-family: "NeueMontreal";
|
font-family: "NeueMontreal";
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.25s ease;
|
||||||
|
line-height: 1.8;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #418df7;
|
color: #3588fd;
|
||||||
|
transform: translateX(3px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -163,10 +433,9 @@
|
||||||
|
|
||||||
.policyDiv {
|
.policyDiv {
|
||||||
background-color: #010101;
|
background-color: #010101;
|
||||||
padding: 0 1rem 2.5rem 1rem;
|
padding: 0 1rem 0.5rem 1rem;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,82 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Solutions Dropdown
|
||||||
|
.solutions-dropdown {
|
||||||
|
position: fixed;
|
||||||
|
top: 4.5rem;
|
||||||
|
left: 12%;
|
||||||
|
background-color: #fff;
|
||||||
|
// padding: 1.5rem 2rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
animation: fadeInIndustry 0.3s ease;
|
||||||
|
box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
|
||||||
|
z-index: 100;
|
||||||
|
min-width: 280px;
|
||||||
|
max-width: 320px;
|
||||||
|
|
||||||
|
.solutions-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0;
|
||||||
|
|
||||||
|
.solution-item {
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
color: #000;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #1473f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.solutions-dropdown-mobile {
|
||||||
|
padding: 0.5rem 0 0.5rem 1.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
.solution-item-mobile {
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.2s;
|
||||||
|
color: #e5e5e5;
|
||||||
|
font-size: 13px;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #1473f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
color: #1473f8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.IndustriesTypes {
|
.IndustriesTypes {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
@ -679,6 +755,67 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mobile Sticky Footer for Book Demo & WhatsApp
|
||||||
|
.mobile-sticky-footer {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.12);
|
||||||
|
padding: 1rem 1.25rem;
|
||||||
|
gap: 1rem;
|
||||||
|
z-index: 999;
|
||||||
|
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-sticky-btn {
|
||||||
|
flex: 1;
|
||||||
|
padding: 1rem 1.75rem;
|
||||||
|
background: linear-gradient(135deg, #000 0%, #1a1a1a 100%);
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-family: "NeueMontreal", sans-serif;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.whatsapp-btn {
|
||||||
|
background: linear-gradient(135deg, #25D366 0%, #1ea952 100%);
|
||||||
|
flex: 0;
|
||||||
|
min-width: 60px;
|
||||||
|
padding: 1rem;
|
||||||
|
box-shadow: 0 4px 12px rgba(37, 211, 102, 0.3);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 6px 16px rgba(37, 211, 102, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes fadeInMenu {
|
@keyframes fadeInMenu {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
|
||||||
|
|
@ -141,11 +141,12 @@
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.slide {
|
.slide {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 60vh;
|
height: 50vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slide-track {
|
.slide-track {
|
||||||
width: calc(200% + 1rem);
|
width: calc(1000% + 1rem);
|
||||||
|
animation: scroll 12s linear infinite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
.OverView-Master {
|
.OverView-Master {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 115vh;
|
min-height: 100vh;
|
||||||
|
height: auto;
|
||||||
background: #000;
|
background: #000;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
@ -42,8 +43,9 @@
|
||||||
|
|
||||||
// Slogan - Hero Title
|
// Slogan - Hero Title
|
||||||
.overviewSlogan {
|
.overviewSlogan {
|
||||||
font-size: 5vw;
|
font-size: 4.5vw;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
width:80vw;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
margin: 6.5rem 1.5rem 0 1.5rem;
|
margin: 6.5rem 1.5rem 0 1.5rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
@ -83,9 +85,10 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: flex-end;
|
align-items: flex-start;
|
||||||
margin: 0 1.5rem;
|
margin: 0 1.5rem;
|
||||||
margin-top: 5.5rem;
|
margin-top: 5.5rem;
|
||||||
|
margin-bottom: 3rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
gap: 3rem;
|
gap: 3rem;
|
||||||
|
|
@ -125,11 +128,12 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1.2rem;
|
gap: 1.2rem;
|
||||||
justify-content: flex-end;
|
justify-content: flex-start;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-height: fit-content;
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
padding:16px 0;
|
padding: 16px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -267,7 +271,7 @@
|
||||||
-webkit-backdrop-filter: blur(30px);
|
-webkit-backdrop-filter: blur(30px);
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.18);
|
border: 1px solid rgba(255, 255, 255, 0.18);
|
||||||
padding: 2rem;
|
padding: 1.75rem;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
margin-right: 5rem;
|
margin-right: 5rem;
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||||
|
|
@ -318,10 +322,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-size: 24px;
|
font-size: 22px;
|
||||||
font-family: "NeueMontreal";
|
font-family: "NeueMontreal";
|
||||||
line-height: 1.4;
|
line-height: 1.35;
|
||||||
margin: 0 0 1.5rem 0;
|
margin: 0 0 1.25rem 0;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
1027
src/check.jsx
1027
src/check.jsx
File diff suppressed because it is too large
Load Diff
101
src/check.scss
101
src/check.scss
|
|
@ -15,6 +15,7 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
@ -28,6 +29,7 @@
|
||||||
gap: 3px;
|
gap: 3px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -108,6 +110,7 @@
|
||||||
transform: translate(0, 0);
|
transform: translate(0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sup {
|
sup {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
background-color: #e68200;
|
background-color: #e68200;
|
||||||
|
|
@ -124,6 +127,7 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
letter-spacing: 0.2px;
|
letter-spacing: 0.2px;
|
||||||
-webkit-text-stroke: 0.2px;
|
-webkit-text-stroke: 0.2px;
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
@ -136,7 +140,7 @@
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
margin-bottom: 4rem;
|
margin-bottom: 0;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 4rem;
|
top: 4rem;
|
||||||
|
|
@ -146,8 +150,12 @@
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
animation: fadeInIndustry 0.5s ease;
|
animation: fadeInIndustry 0.5s ease;
|
||||||
height: 85vh;
|
height: 85vh;
|
||||||
|
max-height: calc(100vh - 5rem);
|
||||||
box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
|
box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
overflow: hidden;
|
||||||
|
isolation: isolate;
|
||||||
|
touch-action: none;
|
||||||
|
|
||||||
&.closing {
|
&.closing {
|
||||||
animation: fadeOutIndustry 0.4s ease;
|
animation: fadeOutIndustry 0.4s ease;
|
||||||
|
|
@ -158,17 +166,41 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.IndustriesOne,
|
.IndustriesOne,
|
||||||
.IndustriesTwo,
|
.IndustriesTwo,
|
||||||
.IndustriesThree {
|
.IndustriesThree {
|
||||||
width: 30%;
|
width: 30%;
|
||||||
font-family: "NeueMontreal";
|
font-family: "NeueMontreal";
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
max-height: calc(85vh - 4rem);
|
||||||
border-right: 2px dashed #9e9e9e;
|
border-right: 2px dashed #9e9e9e;
|
||||||
height: 80vh;
|
overflow-y: auto;
|
||||||
overflow: auto;
|
overflow-x: hidden;
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
padding-bottom: 4rem;
|
padding-bottom: 2rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
touch-action: pan-y;
|
||||||
|
|
||||||
|
// Custom scrollbar styling
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background: #f1f1f1;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: #888;
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #555;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
@ -203,6 +235,7 @@
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #3588fd;
|
color: #3588fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
background-color: rgba(255, 115, 0, 0.966);
|
background-color: rgba(255, 115, 0, 0.966);
|
||||||
|
|
@ -223,6 +256,7 @@
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
@ -247,10 +281,12 @@
|
||||||
&.closing {
|
&.closing {
|
||||||
animation: fadeOutMenu 0.4s ease;
|
animation: fadeOutMenu 0.4s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1300px) {
|
@media (max-width: 1300px) {
|
||||||
top: 8%;
|
top: 8%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ResNavHeader {
|
.ResNavHeader {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -258,12 +294,14 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ResNavHeaderClose {
|
.ResNavHeaderClose {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-family: "NeueMontreal";
|
font-family: "NeueMontreal";
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
div {
|
div {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -271,6 +309,7 @@
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ResnavbarOption {
|
.ResnavbarOption {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-family: "NeueMontreal";
|
font-family: "NeueMontreal";
|
||||||
|
|
@ -279,6 +318,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
|
||||||
.indusOpen {
|
.indusOpen {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -289,7 +329,38 @@
|
||||||
border-bottom: 2px dashed #868686;
|
border-bottom: 2px dashed #868686;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.IndustriesTypes {
|
||||||
|
position: relative;
|
||||||
|
top: unset;
|
||||||
|
left: unset;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #383838;
|
||||||
|
color: #fff;
|
||||||
|
overflow: auto;
|
||||||
|
isolation: unset;
|
||||||
|
touch-action: unset;
|
||||||
|
height: 70vh;
|
||||||
|
box-shadow: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.IndustriesOne,
|
||||||
|
.IndustriesTwo,
|
||||||
|
.IndustriesThree {
|
||||||
|
border-right: none;
|
||||||
|
height: max-content;
|
||||||
|
max-height: 40vh;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
|
>div,
|
||||||
|
>p {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.industryRes {
|
.industryRes {
|
||||||
background-color: #383838;
|
background-color: #383838;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|
@ -312,12 +383,14 @@
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-family: "NeueMontreal";
|
font-family: "NeueMontreal";
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
color: #cecece;
|
color: #cecece;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #3588fd;
|
color: #3588fd;
|
||||||
}
|
}
|
||||||
|
|
@ -331,6 +404,7 @@
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #3588fd;
|
color: #3588fd;
|
||||||
}
|
}
|
||||||
|
|
@ -345,6 +419,7 @@
|
||||||
font-family: "NeueMontreal";
|
font-family: "NeueMontreal";
|
||||||
margin-top: 3rem;
|
margin-top: 3rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
sup {
|
sup {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
background-color: #e68200;
|
background-color: #e68200;
|
||||||
|
|
@ -421,12 +496,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeInMenu {
|
@keyframes fadeInMenu {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
// transform: translateY(-50px);
|
// transform: translateY(-50px);
|
||||||
height: 0vh;
|
height: 0vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
// transform: translateY(0);
|
// transform: translateY(0);
|
||||||
|
|
@ -440,18 +517,21 @@
|
||||||
// transform: translateY(0);
|
// transform: translateY(0);
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
// transform: translateY(-50px);
|
// transform: translateY(-50px);
|
||||||
height: 0vh;
|
height: 0vh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeInIndustry {
|
@keyframes fadeInIndustry {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(-10px);
|
transform: translateY(-10px);
|
||||||
height: 0vh;
|
height: 0vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
|
|
@ -465,18 +545,21 @@
|
||||||
height: 80vh;
|
height: 80vh;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
height: 0vh;
|
height: 0vh;
|
||||||
transform: translateY(-10px);
|
transform: translateY(-10px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeInCompany {
|
@keyframes fadeInCompany {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(-10px);
|
transform: translateY(-10px);
|
||||||
height: 0px;
|
height: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
|
|
@ -490,6 +573,7 @@
|
||||||
height: 250px;
|
height: 250px;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
height: 0px;
|
height: 0px;
|
||||||
|
|
@ -502,6 +586,7 @@
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(-10px);
|
transform: translateY(-10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
|
|
@ -513,6 +598,7 @@
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(-10px);
|
transform: translateY(-10px);
|
||||||
|
|
@ -524,6 +610,7 @@
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(-10px);
|
transform: translateY(-10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
|
|
@ -535,6 +622,7 @@
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(-10px);
|
transform: translateY(-10px);
|
||||||
|
|
@ -546,6 +634,7 @@
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(100%);
|
transform: translateX(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
|
|
@ -557,6 +646,7 @@
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(100%);
|
transform: translateX(100%);
|
||||||
|
|
@ -588,6 +678,7 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
letter-spacing: 0.2px;
|
letter-spacing: 0.2px;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #3588fd;
|
color: #3588fd;
|
||||||
}
|
}
|
||||||
|
|
@ -598,4 +689,4 @@
|
||||||
.IndustriesTypes {
|
.IndustriesTypes {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -93,11 +93,14 @@ import SignIn from "./PozoApp/Components/SignIn.jsx";
|
||||||
import LiveSession from "./PozoApp/Components/LiveSession.jsx";
|
import LiveSession from "./PozoApp/Components/LiveSession.jsx";
|
||||||
import ContactUs from "./PozoApp/Components/ContactUs.jsx";
|
import ContactUs from "./PozoApp/Components/ContactUs.jsx";
|
||||||
import PricingPozoApp from "./PozoApp/Components/PricingPozoApp.jsx";
|
import PricingPozoApp from "./PozoApp/Components/PricingPozoApp.jsx";
|
||||||
|
import Solutions from "./PozoApp/Pages/Solutions.jsx";
|
||||||
|
import CaseStudies from "./PozoApp/Pages/CaseStudies.jsx";
|
||||||
import GatewayMasterConfiguration from "./Pages/GatewayMasterConfiguration/GatewayMasterConfiguration.jsx";
|
import GatewayMasterConfiguration from "./Pages/GatewayMasterConfiguration/GatewayMasterConfiguration.jsx";
|
||||||
import GatewayMasterConfigurationList from "./Pages/GatewayMasterConfiguration/GatewayMasterConfigurationList.jsx";
|
import GatewayMasterConfigurationList from "./Pages/GatewayMasterConfiguration/GatewayMasterConfigurationList.jsx";
|
||||||
import AdminPanelWrapper from "./AdminPanel/AdminPanelWrapper.jsx";
|
import AdminPanelWrapper from "./AdminPanel/AdminPanelWrapper.jsx";
|
||||||
import Blog from "./AdminPanel/Blog/Blog.jsx";
|
import Blog from "./AdminPanel/Blog/Blog.jsx";
|
||||||
import BlogDetail from "./AdminPanel/Blog/BlogDetail.jsx";
|
import BlogDetail from "./AdminPanel/Blog/BlogDetail.jsx";
|
||||||
|
import LandingPageCMS from "./LandingPageCMS/LandingPageCMS.jsx";
|
||||||
import PostEditorPage from "./Pages/PostEditorPage.jsx";
|
import PostEditorPage from "./Pages/PostEditorPage.jsx";
|
||||||
import PrivacyPolicy from "./PozoApp/Company/PrivacyPolicy.jsx";
|
import PrivacyPolicy from "./PozoApp/Company/PrivacyPolicy.jsx";
|
||||||
import CookiePolicy from "./PozoApp/Company/CookiePolicy.jsx";
|
import CookiePolicy from "./PozoApp/Company/CookiePolicy.jsx";
|
||||||
|
|
@ -117,6 +120,12 @@ export const routesConfig = [
|
||||||
access: "Marketing",
|
access: "Marketing",
|
||||||
empAccess: "Admin Panel",
|
empAccess: "Admin Panel",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: `${subDirectory}landing-cms`,
|
||||||
|
component: LandingPageCMS,
|
||||||
|
access: "Marketing",
|
||||||
|
empAccess: "Admin Panel",
|
||||||
|
},
|
||||||
{ path: `${subDirectory}:appName`, component: Template, access: "Public" },
|
{ path: `${subDirectory}:appName`, component: Template, access: "Public" },
|
||||||
{ path: `${subDirectory}feature1`, component: Feature1 },
|
{ path: `${subDirectory}feature1`, component: Feature1 },
|
||||||
{ path: `${subDirectory}pdf`, component: PdfPage, access: "Admin" },
|
{ path: `${subDirectory}pdf`, component: PdfPage, access: "Admin" },
|
||||||
|
|
@ -168,7 +177,7 @@ export const routesConfig = [
|
||||||
{ path: `${subDirectory}homepage`, component: PublicHome, access: "Public" },
|
{ path: `${subDirectory}homepage`, component: PublicHome, access: "Public" },
|
||||||
// { path: `${subDirectory}signinnew`, component: SignIn, access: "Public" },
|
// { path: `${subDirectory}signinnew`, component: SignIn, access: "Public" },
|
||||||
{
|
{
|
||||||
path: `${subDirectory}pricing-pozoapp`,
|
path: `${subDirectory}pricing`,
|
||||||
component: PricingPozoApp,
|
component: PricingPozoApp,
|
||||||
access: "Public",
|
access: "Public",
|
||||||
},
|
},
|
||||||
|
|
@ -178,6 +187,8 @@ export const routesConfig = [
|
||||||
access: "Public",
|
access: "Public",
|
||||||
},
|
},
|
||||||
{ path: `${subDirectory}contact-us`, component: ContactUs, access: "Public" },
|
{ path: `${subDirectory}contact-us`, component: ContactUs, access: "Public" },
|
||||||
|
{ path: `${subDirectory}solutions`, component: Solutions, access: "Public" },
|
||||||
|
{ path: `${subDirectory}case-studies`, component: CaseStudies, access: "Public" },
|
||||||
{ path: `${subDirectory}blog`, component: Blog, access: "Public" },
|
{ path: `${subDirectory}blog`, component: Blog, access: "Public" },
|
||||||
// {
|
// {
|
||||||
// path: `${subDirectory}blog/blog-details/:id`,
|
// path: `${subDirectory}blog/blog-details/:id`,
|
||||||
|
|
|
||||||
|
|
@ -65,13 +65,14 @@ export default defineConfig(({ command, mode, ssrBuild }) => {
|
||||||
// },
|
// },
|
||||||
// }),
|
// }),
|
||||||
],
|
],
|
||||||
base: "/home/",
|
base: "/", // Changed from "/home/" to "/" for clean SEO URLs
|
||||||
envDir: "src",
|
envDir: "src",
|
||||||
envPrefix: "ENV_",
|
envPrefix: "ENV_",
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
|
base: "/", // Changed from default to "/" for consistency
|
||||||
envDir: "src",
|
envDir: "src",
|
||||||
envPrefix: "ENV_",
|
envPrefix: "ENV_",
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue