334 lines
9.3 KiB
TypeScript
334 lines
9.3 KiB
TypeScript
import { useState } from 'react'
|
||
import { team } from '@/data/team'
|
||
|
||
/* ─── derived stats ──────────────────────────────────────── */
|
||
const totalReports = team.reduce((sum, m) => sum + m.reportCount, 0)
|
||
const memberCount = team.length
|
||
const combinedYears = 85
|
||
|
||
/* ─── member card ────────────────────────────────────────── */
|
||
function MemberCard({ member }: { member: (typeof team)[0] }) {
|
||
const [hovered, setHovered] = useState(false)
|
||
const [bioExpanded, setBioExpanded] = useState(false)
|
||
|
||
return (
|
||
<article
|
||
style={{
|
||
border: '1px solid var(--rule-thin)',
|
||
background: hovered ? 'var(--paper-2)' : 'var(--paper)',
|
||
transition: 'background 140ms',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
}}
|
||
onMouseEnter={() => setHovered(true)}
|
||
onMouseLeave={() => setHovered(false)}
|
||
>
|
||
{/* card header */}
|
||
<div
|
||
style={{
|
||
padding: '24px 20px 16px',
|
||
borderBottom: '1px solid var(--rule-thin)',
|
||
display: 'flex',
|
||
alignItems: 'flex-start',
|
||
gap: 16,
|
||
}}
|
||
>
|
||
{/* initial avatar */}
|
||
<div
|
||
style={{
|
||
width: 56,
|
||
height: 56,
|
||
background: 'var(--ink)',
|
||
color: 'var(--paper)',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
fontSize: 22,
|
||
fontWeight: 900,
|
||
flexShrink: 0,
|
||
letterSpacing: '-0.5px',
|
||
}}
|
||
>
|
||
{member.initial}
|
||
</div>
|
||
|
||
<div style={{ flex: 1, minWidth: 0 }}>
|
||
<h3
|
||
style={{
|
||
fontSize: 15,
|
||
fontWeight: 800,
|
||
color: 'var(--ink)',
|
||
lineHeight: 1.3,
|
||
letterSpacing: '-0.3px',
|
||
marginBottom: 4,
|
||
}}
|
||
>
|
||
{member.name}
|
||
</h3>
|
||
<span
|
||
style={{
|
||
fontSize: 10,
|
||
fontWeight: 700,
|
||
color: 'var(--red)',
|
||
textTransform: 'uppercase',
|
||
letterSpacing: '1.5px',
|
||
display: 'block',
|
||
}}
|
||
>
|
||
{member.role}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* bio */}
|
||
<div style={{ padding: '14px 20px', borderBottom: '1px solid var(--rule-thin)' }}>
|
||
<p
|
||
style={{
|
||
fontSize: 13,
|
||
fontWeight: 300,
|
||
color: 'var(--ink-3)',
|
||
lineHeight: 1.85,
|
||
display: '-webkit-box',
|
||
WebkitLineClamp: bioExpanded ? undefined : 3,
|
||
WebkitBoxOrient: 'vertical' as const,
|
||
overflow: bioExpanded ? 'visible' : 'hidden',
|
||
}}
|
||
>
|
||
{member.bio}
|
||
</p>
|
||
{!bioExpanded && member.bio.length > 120 && (
|
||
<button
|
||
onClick={() => setBioExpanded(true)}
|
||
style={{
|
||
marginTop: 6,
|
||
fontSize: 11,
|
||
fontWeight: 600,
|
||
color: 'var(--ink-4)',
|
||
background: 'none',
|
||
border: 'none',
|
||
cursor: 'pointer',
|
||
fontFamily: 'inherit',
|
||
padding: 0,
|
||
textDecoration: 'underline',
|
||
textDecorationStyle: 'dotted',
|
||
}}
|
||
>
|
||
بیشتر
|
||
</button>
|
||
)}
|
||
</div>
|
||
|
||
{/* expertise tags */}
|
||
<div style={{ padding: '12px 20px', borderBottom: '1px solid var(--rule-thin)' }}>
|
||
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
|
||
{member.expertise.map((tag) => (
|
||
<span
|
||
key={tag}
|
||
style={{
|
||
fontSize: 10,
|
||
fontWeight: 500,
|
||
color: 'var(--ink-3)',
|
||
background: 'var(--paper-3)',
|
||
padding: '3px 8px',
|
||
letterSpacing: '0.2px',
|
||
}}
|
||
>
|
||
{tag}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* footer: report count + email */}
|
||
<div
|
||
style={{
|
||
padding: '12px 20px',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'space-between',
|
||
marginTop: 'auto',
|
||
}}
|
||
>
|
||
<div style={{ display: 'flex', alignItems: 'baseline', gap: 4 }}>
|
||
<span
|
||
style={{
|
||
fontSize: 20,
|
||
fontWeight: 900,
|
||
color: 'var(--ink)',
|
||
letterSpacing: '-0.5px',
|
||
lineHeight: 1,
|
||
}}
|
||
>
|
||
{member.reportCount.toLocaleString('fa-IR')}
|
||
</span>
|
||
<span style={{ fontSize: 11, fontWeight: 400, color: 'var(--ink-5)' }}>
|
||
گزارش منتشرشده
|
||
</span>
|
||
</div>
|
||
|
||
{member.email && (
|
||
<a
|
||
href={`mailto:${member.email}`}
|
||
style={{
|
||
fontSize: 10,
|
||
color: 'var(--ink-5)',
|
||
textDecoration: 'none',
|
||
fontWeight: 400,
|
||
letterSpacing: '0.2px',
|
||
direction: 'ltr',
|
||
display: 'inline-block',
|
||
}}
|
||
>
|
||
{member.email}
|
||
</a>
|
||
)}
|
||
</div>
|
||
</article>
|
||
)
|
||
}
|
||
|
||
/* ─── main component ─────────────────────────────────────── */
|
||
export default function Team() {
|
||
return (
|
||
<div
|
||
style={{
|
||
maxWidth: 1280,
|
||
margin: '0 auto',
|
||
padding: '64px 48px',
|
||
direction: 'rtl',
|
||
}}
|
||
>
|
||
{/* ─── Section header ────────────────────────────────── */}
|
||
<div
|
||
style={{
|
||
display: 'flex',
|
||
alignItems: 'stretch',
|
||
borderBottom: '3px solid var(--ink)',
|
||
marginBottom: 40,
|
||
gap: 0,
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
background: 'var(--ink)',
|
||
padding: '14px 28px',
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
}}
|
||
>
|
||
<h1
|
||
style={{
|
||
fontSize: 24,
|
||
fontWeight: 900,
|
||
color: 'var(--paper)',
|
||
letterSpacing: '-0.5px',
|
||
whiteSpace: 'nowrap',
|
||
}}
|
||
>
|
||
تیم تحریریه
|
||
</h1>
|
||
</div>
|
||
|
||
<div style={{ flex: 1 }} />
|
||
|
||
<div
|
||
style={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
padding: '14px 0',
|
||
}}
|
||
>
|
||
<span
|
||
style={{
|
||
fontSize: 13,
|
||
fontWeight: 300,
|
||
color: 'var(--ink-4)',
|
||
fontStyle: 'italic',
|
||
}}
|
||
>
|
||
متخصصان برجسته صنعت فولاد ایران
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* ─── Stats row ─────────────────────────────────────── */}
|
||
<div
|
||
style={{
|
||
display: 'grid',
|
||
gridTemplateColumns: 'repeat(3, 1fr)',
|
||
border: '1px solid var(--rule-thin)',
|
||
marginBottom: 48,
|
||
}}
|
||
>
|
||
{[
|
||
{ value: totalReports.toLocaleString('fa-IR'), label: 'گزارش منتشرشده' },
|
||
{ value: memberCount.toLocaleString('fa-IR'), label: 'عضو تحریریه' },
|
||
{ value: `${combinedYears.toLocaleString('fa-IR')} سال`, label: 'تجربه ترکیبی' },
|
||
].map((stat, i) => (
|
||
<div
|
||
key={i}
|
||
style={{
|
||
padding: '28px 32px',
|
||
borderLeft: i < 2 ? '1px solid var(--rule-thin)' : 'none',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
gap: 4,
|
||
}}
|
||
>
|
||
<span
|
||
style={{
|
||
fontSize: 42,
|
||
fontWeight: 900,
|
||
color: 'var(--ink)',
|
||
lineHeight: 1,
|
||
letterSpacing: '-1.5px',
|
||
display: 'block',
|
||
}}
|
||
>
|
||
{stat.value}
|
||
</span>
|
||
<span
|
||
style={{
|
||
fontSize: 12,
|
||
fontWeight: 400,
|
||
color: 'var(--ink-5)',
|
||
letterSpacing: '0.3px',
|
||
}}
|
||
>
|
||
{stat.label}
|
||
</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
{/* ─── Member grid ───────────────────────────────────── */}
|
||
<div
|
||
className="team-grid"
|
||
style={{
|
||
display: 'grid',
|
||
gridTemplateColumns: 'repeat(3, 1fr)',
|
||
gap: 1,
|
||
background: 'var(--rule-thin)',
|
||
}}
|
||
>
|
||
{team.map((member) => (
|
||
<MemberCard key={member.id} member={member} />
|
||
))}
|
||
</div>
|
||
|
||
<style>{`
|
||
@media (max-width: 767px) {
|
||
.team-grid {
|
||
grid-template-columns: 1fr !important;
|
||
}
|
||
}
|
||
@media (max-width: 1024px) and (min-width: 768px) {
|
||
.team-grid {
|
||
grid-template-columns: repeat(2, 1fr) !important;
|
||
}
|
||
}
|
||
`}</style>
|
||
</div>
|
||
)
|
||
}
|