erp-platform/ui/src/views/public/About.tsx

210 lines
6.3 KiB
TypeScript
Raw Normal View History

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'
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
// 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">
{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">
<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>
<p className="text-center p-5 text-blue-800">
{translate(aboutPageData.descriptions[1])}
2025-08-14 07:10:56 +00:00
</p>
<p>
{translate(aboutPageData.descriptions[2])}
2025-08-14 07:10:56 +00:00
</p>
<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">
{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