About Sayfası dinamik hale getiriliyor.
This commit is contained in:
parent
13362f4745
commit
6fdc2c3231
1 changed files with 137 additions and 51 deletions
|
|
@ -8,14 +8,101 @@ import {
|
|||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { useCountUp } from '@/utils/hooks/useCountUp'
|
||||
import { Helmet } from 'react-helmet'
|
||||
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[]
|
||||
}
|
||||
|
||||
const About: React.FC = () => {
|
||||
const { translate } = useLocalization()
|
||||
|
||||
// Counter animations
|
||||
const clientsCount = useCountUp({ end: 300, suffix: '+', duration: 2500 })
|
||||
const experienceCount = useCountUp({ end: 20, suffix: '+', duration: 2000 })
|
||||
const countriesCount = useCountUp({ end: 3, duration: 1500 })
|
||||
// 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!
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -49,32 +136,35 @@ const About: React.FC = () => {
|
|||
<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">
|
||||
<div className="text-center" ref={clientsCount.elementRef}>
|
||||
<FaUsers className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
||||
<div className="text-4xl font-bold text-gray-900 mb-2">
|
||||
{clientsCount.displayValue}
|
||||
</div>
|
||||
<div className="text-gray-600">{translate('::Public.about.stats.clients')}</div>
|
||||
</div>
|
||||
<div className="text-center" ref={experienceCount.elementRef}>
|
||||
<FaAward className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
||||
<div className="text-4xl font-bold text-gray-900 mb-2">
|
||||
{experienceCount.displayValue}
|
||||
</div>
|
||||
<div className="text-gray-600">{translate('::Public.about.stats.experience')}</div>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<FaClock className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
||||
<div className="text-4xl font-bold text-gray-900 mb-2">7/24</div>
|
||||
<div className="text-gray-600">{translate('::Public.about.stats.support')}</div>
|
||||
</div>
|
||||
<div className="text-center" ref={countriesCount.elementRef}>
|
||||
<FaGlobe className="w-12 h-12 text-blue-600 mx-auto mb-4" />
|
||||
<div className="text-4xl font-bold text-gray-900 mb-2">
|
||||
{countriesCount.displayValue}
|
||||
</div>
|
||||
<div className="text-gray-600">{translate('::Public.about.stats.countries')}</div>
|
||||
</div>
|
||||
{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>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -83,35 +173,31 @@ const About: React.FC = () => {
|
|||
<div className="py-6">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="mb-6">
|
||||
<div className="space-y-6 mx-auto mx-auto text-gray-800 text-lg leading-relaxed">
|
||||
<p className="bg-white p-5 shadow-md border-l-4 border-blue-600">
|
||||
{translate('::Public.about.description.part1')}
|
||||
<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])}
|
||||
</p>
|
||||
<p className="italic text-center text-blue-700 font-semibold">
|
||||
{translate('::Public.about.description.motto')}
|
||||
<p className="text-center p-5 text-blue-800">
|
||||
{translate(aboutPageData.descriptions[1])}
|
||||
</p>
|
||||
<p className="bg-white p-5 shadow-md border-l-4 border-blue-600">
|
||||
{translate('::Public.about.description.part2')}
|
||||
<p>
|
||||
{translate(aboutPageData.descriptions[2])}
|
||||
</p>
|
||||
<p className="text-center text-blue-700 font-medium">
|
||||
{translate('::Public.about.description.closing')}
|
||||
<p className="text-center p-5 text-blue-800">
|
||||
{translate(aboutPageData.descriptions[3])}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12">
|
||||
<div className="bg-white p-8 rounded-xl shadow-lg">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-4">
|
||||
{translate('::Public.about.mission')}
|
||||
</h3>
|
||||
<p className="text-gray-700">{translate('::Public.about.mission.desc')}</p>
|
||||
</div>
|
||||
<div className="bg-white p-8 rounded-xl shadow-lg">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-4">
|
||||
{translate('::Public.about.vision')}
|
||||
</h3>
|
||||
<p className="text-gray-700">{translate('::Public.about.vision.desc')}</p>
|
||||
</div>
|
||||
{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>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue