feat: Containerize services with Docker Compose (PostgreSQL, Strapi CMS, Express Backend, Nginx Frontend) on custom ports >9000

This commit is contained in:
Vishva
2026-08-03 19:58:10 +05:30
parent 48f8ab9716
commit 6244fd4072
247 changed files with 56672 additions and 169 deletions
+96 -14
View File
@@ -12,6 +12,9 @@ import AboutUsPage from './components/AboutUsPage';
import TurnstileCaptcha from './components/TurnstileCaptcha';
import GlassmorphicSelect from './components/GlassmorphicSelect';
import GlassmorphicDatePicker from './components/GlassmorphicDatePicker';
import BlogDetailPage from './components/BlogDetailPage';
import CareersPage from './components/CareersPage';
import BlogsPage from './components/BlogsPage';
// Reusable Scroll Reveal Wrapper with Reduced Motion Support
function Reveal({ children, delay = 0, style }) {
@@ -405,24 +408,60 @@ export default function App({ previewMode = false }) {
scrollTimeout = setTimeout(handleScrollEnd, 800);
};
const [selectedBlog, setSelectedBlog] = useState(null);
const handleSelectBlog = (blog) => {
setNavbarVisible(true);
setMobileMenuOpen(false);
setSelectedBlog(blog);
setCurrentPage('blog');
window.location.hash = blog?.slug ? `blog-${blog.slug}` : 'blog';
smoothScrollTo(0);
};
useEffect(() => {
const syncPageFromHash = () => {
const hash = window.location.hash;
if (hash === '#contact' || hash === '#contactus') {
const syncPageFromHash = (shouldScroll = false) => {
const hash = window.location.hash.replace('#', '');
if (hash === 'contact' || hash === 'contactus') {
setSelectedBlog(null);
setCurrentPage('contact');
setActiveSection('contactus');
smoothScrollTo(0);
} else if (hash === '#about' || hash === '#aboutus') {
if (shouldScroll) smoothScrollTo(0);
} else if (hash === 'about' || hash === 'aboutus') {
setSelectedBlog(null);
setCurrentPage('about');
setActiveSection('aboutus');
smoothScrollTo(0);
} else if (hash === '#home' || hash === '') {
if (shouldScroll) smoothScrollTo(0);
} else if (hash === 'careers') {
setSelectedBlog(null);
setCurrentPage('careers');
setActiveSection('careers');
if (shouldScroll) smoothScrollTo(0);
} else if (hash === 'blogs') {
setSelectedBlog(null);
setCurrentPage('blogs');
setActiveSection('blogs');
if (shouldScroll) smoothScrollTo(0);
} else if (hash.startsWith('blog-') || hash === 'blog') {
const slug = hash.replace('blog-', '');
const found = insights.find(b => b.slug === slug || String(b.id) === slug);
if (found) {
setSelectedBlog(prev => (prev && (prev.id === found.id || (prev.slug && prev.slug === found.slug)) ? prev : found));
} else if (insights && insights.length > 0) {
setSelectedBlog(prev => prev || insights[0]);
}
setCurrentPage('blog');
if (shouldScroll) smoothScrollTo(0);
} else if (hash === 'home' || hash === '') {
setSelectedBlog(null);
setCurrentPage('home');
}
};
window.addEventListener('hashchange', syncPageFromHash);
return () => window.removeEventListener('hashchange', syncPageFromHash);
}, []);
syncPageFromHash(false);
const handleHashChange = () => syncPageFromHash(true);
window.addEventListener('hashchange', handleHashChange);
return () => window.removeEventListener('hashchange', handleHashChange);
}, [insights]);
const [hoveredItem, setHoveredItem] = useState(null);
const [showCareersAcknowledgement, setShowCareersAcknowledgement] = useState(false);
const [isStrategyOpen, setIsStrategyOpen] = useState(false);
@@ -539,6 +578,7 @@ export default function App({ previewMode = false }) {
}, [previewMode, currentPage]);
const getActiveNavItem = () => {
if (currentPage === 'blogs' || currentPage === 'blog') return 'Blogs';
if (currentPage === 'contact') return 'Contact Us';
if (currentPage === 'about') return 'About Us';
switch (activeSection) {
@@ -549,8 +589,10 @@ export default function App({ previewMode = false }) {
case 'whyus':
return 'About Us';
case 'products':
case 'insights':
return 'Products';
case 'insights':
case 'blogs':
return 'Blogs';
case 'contactus':
return 'Contact Us';
default:
@@ -582,7 +624,7 @@ export default function App({ previewMode = false }) {
};
const sectionX = isMobile ? '1.25rem' : '4rem';
const navItems = ['Home', 'About Us', 'Products', 'Careers', 'Contact Us'];
const navItems = ['Home', 'About Us', 'Products', 'Blogs', 'Careers', 'Contact Us'];
const NAV_OFFSET = isMobile ? 72 : 88;
const scrollToSection = (sectionId) => {
@@ -600,11 +642,21 @@ export default function App({ previewMode = false }) {
const handleNavClick = (item) => {
setNavbarVisible(true);
setMobileMenuOpen(false);
setSelectedBlog(null);
if (item === 'Careers') {
setIsCareersOpen(true);
return;
}
if (item === 'Blogs') {
setCurrentPage('blogs');
setActiveSection('blogs');
window.location.hash = 'blogs';
smoothScrollTo(0);
return;
}
if (item === 'Contact Us') {
setCurrentPage('contact');
setActiveSection('contactus');
@@ -645,10 +697,12 @@ export default function App({ previewMode = false }) {
if (currentPage !== 'home') {
setCurrentPage('home');
setActiveSection(id || 'home');
window.location.hash = id || 'home';
setTimeout(() => doScroll(id), 350);
return;
}
window.location.hash = id || 'home';
doScroll(id);
};
@@ -891,6 +945,12 @@ export default function App({ previewMode = false }) {
<ContactSection isMobile={isMobile} onOpenStrategy={() => setIsStrategyOpen(true)} />
) : currentPage === 'about' ? (
<AboutUsPage isMobile={isMobile} onOpenStrategy={() => setIsStrategyOpen(true)} onNavigate={handleNavClick} />
) : currentPage === 'careers' ? (
<CareersPage isMobile={isMobile} onNavigate={handleNavClick} onOpenStrategy={() => setIsStrategyOpen(true)} />
) : currentPage === 'blogs' ? (
<BlogsPage blogs={insights} isMobile={isMobile} onSelectBlog={handleSelectBlog} onNavigate={handleNavClick} />
) : currentPage === 'blog' ? (
<BlogDetailPage blog={selectedBlog || insights[0]} allBlogs={insights} isMobile={isMobile} onNavigate={handleNavClick} onSelectBlog={handleSelectBlog} />
) : (
<>
{/* Main Homepage Content */}
@@ -1956,8 +2016,29 @@ export default function App({ previewMode = false }) {
</p>
</div>
{/* Nav Arrows */}
<div style={{ display: 'flex', gap: '0.6rem', alignItems: 'center', flexShrink: 0, marginTop: '0.5rem' }}>
{/* Nav Arrows & View All Blogs */}
<div style={{ display: 'flex', gap: '0.75rem', alignItems: 'center', flexShrink: 0, marginTop: '0.5rem', flexWrap: 'wrap' }}>
<button
onClick={() => handleNavClick('Blogs')}
style={{
padding: '0.55rem 1.25rem',
borderRadius: '50px',
background: 'rgba(56,189,248,0.12)',
border: '1px solid rgba(56,189,248,0.3)',
color: '#38bdf8',
fontWeight: 600,
fontSize: '0.85rem',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
gap: '0.4rem',
transition: 'all 0.2s ease',
}}
onMouseEnter={e => { e.currentTarget.style.background = '#38bdf8'; e.currentTarget.style.color = '#000'; }}
onMouseLeave={e => { e.currentTarget.style.background = 'rgba(56,189,248,0.12)'; e.currentTarget.style.color = '#38bdf8'; }}
>
View All Blogs <ArrowRight size={14} />
</button>
<button
onClick={() => scrollBlogCarousel(-1)}
style={{
@@ -2022,6 +2103,7 @@ export default function App({ previewMode = false }) {
>
<div
className="blog-card"
onClick={() => handleSelectBlog(insight)}
style={{
width: '100%',
height: '100%',