2025-08-11 06:34:44 +00:00
|
|
|
import View from '@/views'
|
|
|
|
|
import React, { useEffect, useState } from 'react'
|
|
|
|
|
import { useLocation, Link } from 'react-router-dom'
|
|
|
|
|
import {
|
|
|
|
|
Menu,
|
|
|
|
|
X,
|
|
|
|
|
Home,
|
|
|
|
|
Info,
|
|
|
|
|
Package,
|
|
|
|
|
Briefcase,
|
|
|
|
|
BookOpen,
|
|
|
|
|
Phone,
|
|
|
|
|
Facebook,
|
|
|
|
|
Twitter,
|
|
|
|
|
Linkedin,
|
|
|
|
|
Instagram,
|
|
|
|
|
MapPin,
|
|
|
|
|
Mail,
|
|
|
|
|
PlayCircle,
|
|
|
|
|
} from 'lucide-react'
|
|
|
|
|
import Logo from '@/views/public/Logo'
|
|
|
|
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
|
|
|
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
|
|
|
import LanguageSelector from '../template/LanguageSelector'
|
|
|
|
|
import Demo from '@/views/public/Demo'
|
|
|
|
|
import { ScrollContext } from '@/contexts/ScrollContext'
|
|
|
|
|
|
|
|
|
|
interface NavLink {
|
|
|
|
|
resourceKey?: string
|
|
|
|
|
name: string
|
|
|
|
|
path?: string
|
|
|
|
|
action?: () => void
|
|
|
|
|
icon?: React.ComponentType<any>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const PublicLayout = () => {
|
|
|
|
|
const location = useLocation()
|
|
|
|
|
const { translate } = useLocalization()
|
|
|
|
|
|
|
|
|
|
const [isOpen, setIsOpen] = useState(false)
|
|
|
|
|
const [scrolled, setScrolled] = useState(false)
|
|
|
|
|
const [isDemoOpen, setIsDemoOpen] = useState(false)
|
|
|
|
|
const currentYear = new Date().getFullYear()
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
window.scrollTo(0, 0)
|
|
|
|
|
}, [location.pathname])
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const handleScroll = () => {
|
|
|
|
|
const isScrolled = window.scrollY > 10
|
|
|
|
|
if (isScrolled !== scrolled) {
|
|
|
|
|
setScrolled(isScrolled)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window.addEventListener('scroll', handleScroll)
|
|
|
|
|
return () => window.removeEventListener('scroll', handleScroll)
|
|
|
|
|
}, [scrolled])
|
|
|
|
|
|
|
|
|
|
const toggleMenu = () => setIsOpen(!isOpen)
|
|
|
|
|
|
|
|
|
|
const navLinks: NavLink[] = [
|
|
|
|
|
{
|
|
|
|
|
resourceKey: 'Public.nav.home',
|
|
|
|
|
name: translate('::Public.nav.home'),
|
2025-08-11 13:43:39 +00:00
|
|
|
path: ROUTES_ENUM.public.home,
|
2025-08-11 06:34:44 +00:00
|
|
|
icon: Home,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
resourceKey: 'Public.nav.about',
|
|
|
|
|
name: translate('::Public.nav.about'),
|
2025-08-11 13:43:39 +00:00
|
|
|
path: ROUTES_ENUM.public.about,
|
2025-08-11 06:34:44 +00:00
|
|
|
icon: Info,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
resourceKey: 'Public.nav.services',
|
|
|
|
|
name: translate('::Public.nav.services'),
|
2025-08-11 13:43:39 +00:00
|
|
|
path: ROUTES_ENUM.public.services,
|
2025-08-11 06:34:44 +00:00
|
|
|
icon: Briefcase,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
resourceKey: 'Public.nav.products',
|
|
|
|
|
name: translate('::Public.nav.products'),
|
2025-08-11 13:43:39 +00:00
|
|
|
path: ROUTES_ENUM.public.products,
|
2025-08-11 06:34:44 +00:00
|
|
|
icon: Package,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
resourceKey: 'Public.nav.blog',
|
|
|
|
|
name: translate('::Public.nav.blog'),
|
2025-08-11 13:43:39 +00:00
|
|
|
path: ROUTES_ENUM.public.blog,
|
2025-08-11 06:34:44 +00:00
|
|
|
icon: BookOpen,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
resourceKey: 'Public.nav.demo',
|
|
|
|
|
name: translate('::Public.nav.demo'),
|
|
|
|
|
action: () => setIsDemoOpen(true),
|
|
|
|
|
icon: PlayCircle,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
resourceKey: 'Public.nav.contact',
|
|
|
|
|
name: translate('::Public.nav.contact'),
|
2025-08-11 13:43:39 +00:00
|
|
|
path: ROUTES_ENUM.public.contact,
|
2025-08-11 06:34:44 +00:00
|
|
|
icon: Phone,
|
|
|
|
|
},
|
2025-08-11 13:43:39 +00:00
|
|
|
{
|
|
|
|
|
resourceKey: 'Public.nav.giris',
|
|
|
|
|
name: translate('::Public.nav.giris'),
|
|
|
|
|
path: ROUTES_ENUM.authenticated.login,
|
|
|
|
|
},
|
2025-08-11 06:34:44 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const getNavItemClass = (resourceKey?: string) => {
|
|
|
|
|
switch (resourceKey) {
|
|
|
|
|
case 'Public.nav.giris':
|
|
|
|
|
return 'bg-blue-600 rounded px-2 py-1'
|
|
|
|
|
case 'Public.nav.basket':
|
|
|
|
|
return 'bg-green-600 rounded px-2 py-1'
|
|
|
|
|
default:
|
|
|
|
|
return ''
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<ScrollContext.Provider value={scrolled}>
|
|
|
|
|
<div className="flex flex-col min-h-screen">
|
|
|
|
|
{/* HEADER */}
|
|
|
|
|
<header
|
|
|
|
|
className={`fixed w-full z-50 transition-all duration-300 ${
|
|
|
|
|
scrolled
|
|
|
|
|
? 'bg-gray-900/95 backdrop-blur-sm shadow-md py-2'
|
|
|
|
|
: 'bg-gray-900/80 backdrop-blur-sm py-4'
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<div className="container mx-auto px-4 flex items-center justify-between">
|
|
|
|
|
<Logo mode="dark" />
|
|
|
|
|
{/* Desktop Navigation */}
|
|
|
|
|
<nav className="hidden md:flex items-center space-x-4">
|
|
|
|
|
{navLinks.map((link) =>
|
|
|
|
|
link.path ? (
|
|
|
|
|
<Link
|
|
|
|
|
key={link.path}
|
|
|
|
|
to={link.path}
|
|
|
|
|
className={`flex items-center gap-1 font-medium text-sm text-white hover:text-blue-400 transition-colors ${getNavItemClass(link.resourceKey)}`}
|
|
|
|
|
>
|
|
|
|
|
{link.icon && <link.icon size={18} />}
|
|
|
|
|
{link.name}
|
|
|
|
|
</Link>
|
|
|
|
|
) : (
|
|
|
|
|
<button
|
|
|
|
|
key={link.name}
|
|
|
|
|
onClick={link.action}
|
|
|
|
|
className={`flex items-center gap-1 font-medium text-sm text-white hover:text-blue-400 transition-colors ${getNavItemClass(link.resourceKey)}`}
|
|
|
|
|
>
|
|
|
|
|
{link.icon && <link.icon size={18} />}
|
|
|
|
|
{link.name}
|
|
|
|
|
</button>
|
|
|
|
|
),
|
|
|
|
|
)}
|
|
|
|
|
<LanguageSelector />
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
{/* Mobile Menu Button */}
|
|
|
|
|
<button className="md:hidden text-white" onClick={toggleMenu} aria-label="Toggle menu">
|
|
|
|
|
{isOpen ? <X size={24} /> : <Menu size={24} />}
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Mobile Navigation */}
|
|
|
|
|
{isOpen && (
|
|
|
|
|
<div className="md:hidden bg-gray-900/95 backdrop-blur-sm shadow-lg">
|
|
|
|
|
<div className="container mx-auto px-4">
|
|
|
|
|
<nav className="flex flex-col space-y-4 py-4">
|
|
|
|
|
{navLinks.map((link) =>
|
|
|
|
|
link.path ? (
|
|
|
|
|
<Link
|
|
|
|
|
key={link.path}
|
|
|
|
|
to={link.path}
|
|
|
|
|
className={`flex items-center gap-1 font-medium text-white hover:text-blue-400 transition-colors ${getNavItemClass(link.resourceKey)}`}
|
|
|
|
|
onClick={toggleMenu}
|
|
|
|
|
>
|
|
|
|
|
{link.icon && <link.icon size={18} />}
|
|
|
|
|
{link.name}
|
|
|
|
|
</Link>
|
|
|
|
|
) : (
|
|
|
|
|
<button
|
|
|
|
|
key={link.name}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
link.action?.()
|
|
|
|
|
toggleMenu()
|
|
|
|
|
}}
|
|
|
|
|
className={`flex items-center gap-1 font-medium text-white hover:text-blue-400 transition-colors text-left ${getNavItemClass(link.resourceKey)}`}
|
|
|
|
|
>
|
|
|
|
|
{link.icon && <link.icon size={18} />}
|
|
|
|
|
{link.name}
|
|
|
|
|
</button>
|
|
|
|
|
),
|
|
|
|
|
)}
|
|
|
|
|
<LanguageSelector />
|
|
|
|
|
</nav>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<main className="flex-grow">
|
|
|
|
|
<View />
|
|
|
|
|
</main>
|
|
|
|
|
|
|
|
|
|
<footer className="bg-gray-900 text-white pt-16 pb-8">
|
|
|
|
|
<div className="container mx-auto px-4">
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
|
|
|
|
<div>
|
|
|
|
|
<Logo mode="dark" />
|
|
|
|
|
<p className="mt-4 text-gray-400 text-sm">
|
|
|
|
|
{translate('::Public.footer.companyInfo')}
|
|
|
|
|
</p>
|
|
|
|
|
<div className="flex space-x-4 mt-6">
|
|
|
|
|
<a
|
|
|
|
|
href="https://facebook.com/sozsoft"
|
|
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener noreferrer"
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
<Facebook size={20} />
|
|
|
|
|
</a>
|
|
|
|
|
<a
|
|
|
|
|
href="https://twitter.com/sozsoft"
|
|
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener noreferrer"
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
<Twitter size={20} />
|
|
|
|
|
</a>
|
|
|
|
|
<a
|
|
|
|
|
href="https://linkedin.com/sozsoft"
|
|
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener noreferrer"
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
<Linkedin size={20} />
|
|
|
|
|
</a>
|
|
|
|
|
<a
|
|
|
|
|
href="https://instagram.com/sozsoft"
|
|
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener noreferrer"
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
<Instagram size={20} />
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Quick Links */}
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-lg font-bold mb-4 text-white">
|
|
|
|
|
{translate('::Public.footer.quickLinksTitle')}
|
|
|
|
|
</h3>
|
|
|
|
|
<ul className="space-y-2">
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.home}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.nav.home')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.products}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.nav.products')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.services}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.nav.services')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.about}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.nav.about')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.blog}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.nav.blog')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.contact}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.nav.contact')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Services */}
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-lg font-bold mb-4 text-white">
|
|
|
|
|
{translate('::Public.footer.servicesTitle')}
|
|
|
|
|
</h3>
|
|
|
|
|
<ul className="space-y-2">
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.services}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.services.software.title')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.services}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.services.web.title')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.services}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.services.mobile.title')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.services}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.services.database.title')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.services}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.services.integration.title')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.services}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.services.consulting.title')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Contact Info */}
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-lg font-bold mb-4 text-white">
|
|
|
|
|
{translate('::Public.nav.contact')}
|
|
|
|
|
</h3>
|
|
|
|
|
<ul className="space-y-3">
|
|
|
|
|
<li className="flex items-start space-x-3">
|
|
|
|
|
<MapPin size={20} className="text-gray-400 mt-1 flex-shrink-0" />
|
|
|
|
|
<span className="text-gray-400">{translate('::Public.footer.address')}</span>
|
|
|
|
|
</li>
|
|
|
|
|
<li className="flex items-center space-x-3">
|
|
|
|
|
<Phone size={20} className="text-gray-400 flex-shrink-0" />
|
|
|
|
|
<a
|
|
|
|
|
href="tel:+905447697638"
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
+90 (544) 769 7 638
|
|
|
|
|
</a>
|
|
|
|
|
</li>
|
|
|
|
|
<li className="flex items-center space-x-3">
|
|
|
|
|
<Mail size={20} className="text-gray-400 flex-shrink-0" />
|
|
|
|
|
<a
|
|
|
|
|
href="mailto:destek@sozsoft.com"
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
destek@sozsoft.com
|
|
|
|
|
</a>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="border-t border-gray-800 mt-12 pt-8">
|
|
|
|
|
<div className="flex flex-col md:flex-row justify-between items-center">
|
|
|
|
|
<p className="text-gray-400 text-sm">
|
|
|
|
|
© {currentYear} Sözsoft. {translate('::Public.footer.copyright')}
|
|
|
|
|
</p>
|
|
|
|
|
<div className="mt-4 md:mt-0">
|
|
|
|
|
<ul className="flex space-x-6 text-sm">
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.about}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.footer.privacyPolicy')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<Link
|
|
|
|
|
to={ROUTES_ENUM.public.about}
|
|
|
|
|
className="text-gray-400 hover:text-white transition-colors"
|
|
|
|
|
>
|
|
|
|
|
{translate('::Public.footer.termsOfUse')}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</footer>
|
|
|
|
|
|
|
|
|
|
{/* Demo Modal */}
|
|
|
|
|
<Demo isOpen={isDemoOpen} onClose={() => setIsDemoOpen(false)} />
|
|
|
|
|
</div>
|
|
|
|
|
</ScrollContext.Provider>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default PublicLayout
|