2025-08-13 07:00:10 +00:00
|
|
|
import React from 'react'
|
2025-08-16 19:47:24 +00:00
|
|
|
import {
|
|
|
|
|
FaUsers,
|
|
|
|
|
FaAward,
|
|
|
|
|
FaClock,
|
|
|
|
|
FaGlobe
|
|
|
|
|
} from 'react-icons/fa';
|
2025-08-13 07:00:10 +00:00
|
|
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
|
|
|
import { useCountUp } from '@/utils/hooks/useCountUp'
|
2025-08-14 07:10:56 +00:00
|
|
|
import { Helmet } from 'react-helmet'
|
2025-08-20 20:16:18 +00:00
|
|
|
import { IconType } from 'react-icons'
|
|
|
|
|
|
|
|
|
|
interface StatItem {
|
|
|
|
|
icon: IconType
|
|
|
|
|
value: string | number
|
|
|
|
|
labelKey: string
|
|
|
|
|
useCounter?: boolean
|
|
|
|
|
counterEnd?: number
|
|
|
|
|
counterSuffix?: string
|
|
|
|
|
counterDuration?: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface ContentSection {
|
|
|
|
|
key: string
|
|
|
|
|
descKey: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface AboutPageData {
|
|
|
|
|
stats: StatItem[]
|
|
|
|
|
descriptions: string[]
|
|
|
|
|
sections: ContentSection[]
|
|
|
|
|
}
|
2025-05-15 10:48:03 +00:00
|
|
|
|
|
|
|
|
const About: React.FC = () => {
|
2025-08-11 06:34:44 +00:00
|
|
|
const { translate } = useLocalization()
|
2025-05-15 10:48:03 +00:00
|
|
|
|
2025-08-20 20:16:18 +00:00
|
|
|
// About page data configuration
|
|
|
|
|
const aboutPageData: AboutPageData = {
|
|
|
|
|
stats: [
|
|
|
|
|
{
|
|
|
|
|
icon: FaUsers,
|
|
|
|
|
value: 300,
|
|
|
|
|
labelKey: '::Public.about.stats.clients',
|
|
|
|
|
useCounter: true,
|
|
|
|
|
counterEnd: 300,
|
|
|
|
|
counterSuffix: '+',
|
|
|
|
|
counterDuration: 2500
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
icon: FaAward,
|
|
|
|
|
value: 20,
|
|
|
|
|
labelKey: '::Public.about.stats.experience',
|
|
|
|
|
useCounter: true,
|
|
|
|
|
counterEnd: 20,
|
|
|
|
|
counterSuffix: '+',
|
|
|
|
|
counterDuration: 2000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
icon: FaClock,
|
|
|
|
|
value: '7/24',
|
|
|
|
|
labelKey: '::Public.about.stats.support',
|
|
|
|
|
useCounter: false
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
icon: FaGlobe,
|
|
|
|
|
value: 3,
|
|
|
|
|
labelKey: '::Public.about.stats.countries',
|
|
|
|
|
useCounter: true,
|
|
|
|
|
counterEnd: 3,
|
|
|
|
|
counterDuration: 1500
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
descriptions: [
|
|
|
|
|
'::Public.about.description.part1',
|
|
|
|
|
'::Public.about.description.motto',
|
|
|
|
|
'::Public.about.description.part2',
|
|
|
|
|
'::Public.about.description.closing'
|
|
|
|
|
],
|
|
|
|
|
sections: [
|
|
|
|
|
{
|
|
|
|
|
key: '::Public.about.mission',
|
|
|
|
|
descKey: '::Public.about.mission.desc'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: '::Public.about.vision',
|
|
|
|
|
descKey: '::Public.about.vision.desc'
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Counter animations based on data
|
|
|
|
|
const clientsCount = useCountUp({
|
|
|
|
|
end: aboutPageData.stats[0].counterEnd!,
|
|
|
|
|
suffix: aboutPageData.stats[0].counterSuffix,
|
|
|
|
|
duration: aboutPageData.stats[0].counterDuration!
|
|
|
|
|
})
|
|
|
|
|
const experienceCount = useCountUp({
|
|
|
|
|
end: aboutPageData.stats[1].counterEnd!,
|
|
|
|
|
suffix: aboutPageData.stats[1].counterSuffix,
|
|
|
|
|
duration: aboutPageData.stats[1].counterDuration!
|
|
|
|
|
})
|
|
|
|
|
const countriesCount = useCountUp({
|
|
|
|
|
end: aboutPageData.stats[3].counterEnd!,
|
|
|
|
|
duration: aboutPageData.stats[3].counterDuration!
|
|
|
|
|
})
|
2025-08-13 07:00:10 +00:00
|
|
|
|
2025-05-15 10:48:03 +00:00
|
|
|
return (
|
2025-08-14 07:10:56 +00:00
|
|
|
<>
|
|
|
|
|
<Helmet
|
|
|
|
|
titleTemplate="%s | Sözsoft"
|
|
|
|
|
title={translate('::' + 'Public.about.title')}
|
|
|
|
|
defaultTitle="Sözsoft"
|
|
|
|
|
></Helmet>
|
|
|
|
|
|
|
|
|
|
<div className="min-h-screen bg-gray-50">
|
|
|
|
|
{/* Hero Section */}
|
|
|
|
|
<div className="relative bg-blue-900 text-white py-12">
|
|
|
|
|
<div
|
|
|
|
|
className="absolute inset-0 opacity-20"
|
|
|
|
|
style={{
|
|
|
|
|
backgroundImage:
|
|
|
|
|
'url("https://images.pexels.com/photos/3183183/pexels-photo-3183183.jpeg?auto=compress&cs=tinysrgb&w=1920")',
|
|
|
|
|
backgroundSize: 'cover',
|
|
|
|
|
backgroundPosition: 'center',
|
|
|
|
|
}}
|
|
|
|
|
></div>
|
|
|
|
|
<div className="container mx-auto pt-20 relative">
|
|
|
|
|
<h1 className="text-5xl font-bold ml-4 mt-3 mb-2 text-white">
|
|
|
|
|
{translate('::Public.about.title')}
|
|
|
|
|
</h1>
|
|
|
|
|
<p className="text-xl max-w-3xl ml-4">{translate('::Public.about.subtitle')}</p>
|
|
|
|
|
</div>
|
2025-05-15 10:48:03 +00:00
|
|
|
</div>
|
|
|
|
|
|
2025-08-14 07:10:56 +00:00
|
|
|
{/* Stats Section */}
|
|
|
|
|
<div className="py-10 bg-white">
|
|
|
|
|
<div className="container mx-auto px-4">
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
|
2025-08-20 20:16:18 +00:00
|
|
|
{aboutPageData.stats.map((stat, index) => {
|
|
|
|
|
const IconComponent = stat.icon
|
|
|
|
|
let displayValue = stat.value
|
|
|
|
|
let elementRef = undefined
|
|
|
|
|
|
|
|
|
|
// Handle counter values
|
|
|
|
|
if (stat.useCounter) {
|
|
|
|
|
if (index === 0) {
|
|
|
|
|
displayValue = clientsCount.displayValue
|
|
|
|
|
elementRef = clientsCount.elementRef
|
|
|
|
|
} else if (index === 1) {
|
|
|
|
|
displayValue = experienceCount.displayValue
|
|
|
|
|
elementRef = experienceCount.elementRef
|
|
|
|
|
} else if (index === 3) {
|
|
|
|
|
displayValue = countriesCount.displayValue
|
|
|
|
|
elementRef = countriesCount.elementRef
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div key={index} className="text-center" ref={elementRef}>
|
|
|
|
|
<IconComponent className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
|
|
|
|
<div className="text-4xl font-bold text-gray-900 mb-2">
|
|
|
|
|
{displayValue}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="text-gray-600">{translate(stat.labelKey)}</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
})}
|
2025-05-15 10:48:03 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-08-14 07:10:56 +00:00
|
|
|
{/* Main Content */}
|
|
|
|
|
<div className="py-6">
|
|
|
|
|
<div className="container mx-auto px-4">
|
|
|
|
|
<div className="mb-6">
|
2025-08-20 20:16:18 +00:00
|
|
|
<div className="p-5 mx-auto mx-auto text-gray-800 text-lg leading-relaxed shadow-md bg-white border-l-4 border-blue-600">
|
|
|
|
|
<p>
|
|
|
|
|
{translate(aboutPageData.descriptions[0])}
|
2025-08-14 07:10:56 +00:00
|
|
|
</p>
|
2025-08-20 20:16:18 +00:00
|
|
|
<p className="text-center p-5 text-blue-800">
|
|
|
|
|
{translate(aboutPageData.descriptions[1])}
|
2025-08-14 07:10:56 +00:00
|
|
|
</p>
|
2025-08-20 20:16:18 +00:00
|
|
|
<p>
|
|
|
|
|
{translate(aboutPageData.descriptions[2])}
|
2025-08-14 07:10:56 +00:00
|
|
|
</p>
|
2025-08-20 20:16:18 +00:00
|
|
|
<p className="text-center p-5 text-blue-800">
|
|
|
|
|
{translate(aboutPageData.descriptions[3])}
|
2025-08-14 07:10:56 +00:00
|
|
|
</p>
|
|
|
|
|
</div>
|
2025-05-15 10:48:03 +00:00
|
|
|
</div>
|
|
|
|
|
|
2025-08-14 07:10:56 +00:00
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12">
|
2025-08-20 20:16:18 +00:00
|
|
|
{aboutPageData.sections.map((section, index) => (
|
|
|
|
|
<div key={index} className="bg-white p-8 rounded-xl shadow-lg">
|
|
|
|
|
<h3 className="text-2xl font-bold text-gray-900 mb-4">
|
|
|
|
|
{translate(section.key)}
|
|
|
|
|
</h3>
|
|
|
|
|
<p className="text-gray-700">{translate(section.descKey)}</p>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
2025-05-15 10:48:03 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-08-14 07:10:56 +00:00
|
|
|
</>
|
2025-08-13 07:00:10 +00:00
|
|
|
)
|
|
|
|
|
}
|
2025-05-15 10:48:03 +00:00
|
|
|
|
2025-08-13 07:00:10 +00:00
|
|
|
export default About
|