steelforesight/src/pages/Team/Team.tsx

334 lines
9.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
)
}