feat: Add Landing Page CMS, enhance Navbar with Solutions dropdown, mobile sticky footer, and optimize homepage features visibility

This commit is contained in:
SridharRajamani 2025-11-06 23:52:53 +05:30
parent 32cc257c87
commit 85bc3359d7
39 changed files with 4288 additions and 1236 deletions

View File

@ -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>

View File

@ -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'

View File

@ -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'

View File

@ -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;
}
}

View File

@ -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");
}, [navigate]); 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);
}
}
};
ensureToken();
sessionCheckFun();
}, [navigate, dispatch]);
const sessionCheckFun=async()=>{ const sessionCheckFun=async()=>{
const UserId = getSession('UserId') const UserId = getSession('UserId')

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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>

View File

@ -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" && (

View File

@ -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()
}, [])
const apicall = async () => { // 🚀 Memoized API call
let res = await dispatch(getCustomertestimonials()).unwrap(); const apicall = useCallback(async () => {
if (res?.data?.statusCode === 1) { try {
setTestimonialsdata(res?.data?.data); const res = await dispatch(getCustomertestimonials()).unwrap();
if (res?.data?.statusCode === 1) {
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>
)} )}

View File

@ -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(() => {

View File

@ -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>

View File

@ -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();
}; };

View File

@ -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>
); );
}; };

View File

@ -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" />

View File

@ -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

View File

@ -35,7 +35,7 @@ const ResponsiveApp = () => {
}; };
const handlePricing = () => { const handlePricing = () => {
navigate(`${subDirectory}pricing-pozoapp`); navigate(`${subDirectory}pricing`);
}; };
const handleNavigateStore = () => { const handleNavigateStore = () => {

View File

@ -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}
/> />

View File

@ -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;

View File

@ -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;
}
}
}
}

View File

@ -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 />
</section>
<section>
<DigitalSection />
</section>
<section>
<PozoVideo />
</section>
{/* Application DropDown */} <Suspense fallback={null}>
{/* <section> <section>
<Industries /> <Offering />
</section> */} </section>
<section> <section>
<TrendingApp /> <DigitalSection />
</section> </section>
<section> <section>
<FaqSection /> <PozoVideo />
</section> </section>
<section> <section>
<Insiders /> <TrendingApp />
</section> </section>
<section> <section>
<Footer /> <FaqSection />
</section> </section>
<section>
<Insiders />
</section>
<section>
<Footer AppCategory={AppCategory} />
</section>
</Suspense>
<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>
</> </>
); );

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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) {

View File

@ -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;

View File

@ -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;
} }
} }
} }

View File

@ -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.

File diff suppressed because it is too large Load Diff

View File

@ -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;
} }

View File

@ -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`,

View File

@ -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_",