1// candidate-card.jsx 2// Shared, themeable candidate dossier card + small primitives. 3// Styling comes from CSS custom properties set by each variant wrapper 4// (.va / .vb / .vc), so the same structure re-skins cleanly. 5// Exports to window: CandidateCard, VideoCircle, CANDIDATE. 6 7const CANDIDATE = { 8 name: "ÐлÑга Ð.", 9 age: "25 леÑ", 10 role: "ÐÐµÐ½ÐµÐ´Ð¶ÐµÑ Ð¿ÑоекÑов", 11 status: "Ð ÑабоÑе", 12 facts: [ 13 ["ÐоÑод", "СанкÑ-ÐеÑеÑбÑÑг"], 14 ["ÐеÑÑо", "ÐлоÑÐ°Ð´Ñ ÐоÑÑÑаниÑ"], 15 ["ÐаÑплаÑа", "60 000 ⽠на ÑÑки"], 16 ["СпеÑиализаÑиÑ", "Ð ÑководиÑÐµÐ»Ñ Ð¿ÑоекÑов"], 17 ["ÐанÑÑоÑÑÑ", "ÐолнаÑ"], 18 ["ЯзÑки", "Ð ÑÑ Â· Ðнгл B2"], 19 ], 20 links: ["Telegram", "ÐÐонÑакÑе"], 21 recruiterStats: [ 22 ["100", "маÑемаÑика"], 23 ["84", "ÑÑÑÑкий"], 24 ["10/10", "видео-инÑеÑвÑÑ"], 25 ], 26 recruiterNote: 27 "ÐÑкÑÑÑаÑ, ÑÑ Ð²Ð°ÑÑÐ²Ð°ÐµÑ Ð±ÑÑÑÑо, оÑвеÑÐ°ÐµÑ Ð¿Ð¾ делÑ. ХоÑÐµÑ Ð² ÑпÑавление пÑоекÑами и гоÑова бÑаÑÑ Ð¾ÑвеÑÑÑвенноÑÑÑ.", 28 aiNote: 29 "ÐеÑÐ¶Ð¸Ñ ÑÑÑÑкÑÑÑÑ ÑазговоÑа, аÑгÑменÑиÑÑÐµÑ Ð¿ÑимеÑами. СилÑнÑе ÑÑоÑÐ¾Ð½Ñ â коммÑникаÑÐ¸Ñ Ð¸ обÑÑаемоÑÑÑ.", 30 cover: 31 "«ÐдÑавÑÑвÑйÑе! ÐÑкликаÑÑÑ, поÑÐ¾Ð¼Ñ ÑÑо Ñ Ð¾ÑÑ Ð·Ð°Ð½Ð¸Ð¼Ð°ÑÑÑÑ ÑпÑавлением пÑоекÑами. ÐÑÐ±Ð»Ñ Ð±ÑÑÑÑо оÑваиваÑÑ Ð½Ð¾Ð²Ð¾Ðµ и доводиÑÑ Ð·Ð°Ð´Ð°Ñи до ÑезÑлÑÑаÑа â гоÑова показаÑÑ ÑÑо в деле»", 32 education: ["ÐазанÑкий Ñед. ÑнивеÑÑиÑеÑ", "Реклама и ÑвÑзи Ñ Ð¾Ð±ÑеÑÑвенноÑÑÑÑ", "2022"], 33 expStats: [ 34 ["5 Ð»ÐµÑ 7 меÑ", "обÑий ÑÑаж"], 35 ["4", "меÑÑа ÑабоÑÑ"], 36 ["~1,5 года", "в ÑÑеднем на меÑÑе"], 37 ], 38 experience: [ 39 { 40 period: "2025 â н.в.", 41 org: "Фонд ÑазвиÑÐ¸Ñ Ð¿ÑедпÑинимаÑелей", 42 title: "главнÑй ÑпеÑиалиÑÑ", 43 desc: "СопÑовождение полÑÑаÑелей ÑÑлÑг, коммÑникаÑиÑ, ÑабоÑа Ñ Ð¾Ñганами влаÑÑи и подÑÑдÑиками.", 44 }, 45 { 46 period: "2021 â 2025", 47 org: "ÐиджиÑал-агенÑÑÑво", 48 title: "пÑодакÑ-менеджеÑ", 49 desc: "УпÑавление маÑкеÑингом и Ñозданием пÑодÑкÑов, кооÑдинаÑÐ¸Ñ Ð¸ÑполниÑелей и ÑÑоков.", 50 }, 51 ], 52}; 53 54// ââ Small primitives ââââââââââââââââââââââââââââââââââââââââââââââ 55function SectionLabel({ children, action }) { 56 return ( 57 <div className="cc-seclabel"> 58 <span>{children}</span> 59 {action ? <a className="cc-seclink">{action} âº</a> : null} 60 </div> 61 ); 62} 63 64function Stat({ value, label }) { 65 return ( 66 <div className="cc-stat"> 67 <div className="cc-stat-v">{value}</div> 68 <div className="cc-stat-l">{label}</div> 69 </div> 70 ); 71} 72 73function VideoTile() { 74 return ( 75 <div className="cc-vtile"> 76 <span className="cc-play" /> 77 </div> 78 ); 79} 80 81// Telegram-style round video bubble (used in team strip) 82function VideoCircle({ id, name, role, size = 92, time = "0:14" }) { 83 return ( 84 <div className="vc-wrap" style={{ width: size }}> 85 <div className="vc-ring" style={{ width: size, height: size }}> 86 <image-slot 87 id={id} 88 shape="circle" 89 style={{ width: size - 8 + "px", height: size - 8 + "px" }} 90 placeholder="" 91 ></image-slot> 92 <span className="vc-play"> 93 <svg width="14" height="16" viewBox="0 0 14 16" aria-hidden="true"> 94 <path d="M1 1.8 12.5 8 1 14.2Z" fill="#fff" /> 95 </svg> 96 </span> 97 <span className="vc-time">{time}</span> 98 </div> 99 <div className="vc-name">{name}</div> 100 <div className="vc-role">{role}</div> 101 </div> 102 ); 103} 104 105// ââ The dossier card ââââââââââââââââââââââââââââââââââââââââââââââ 106function CandidateCard({ idPrefix = "a" }) { 107 const c = CANDIDATE; 108 return (
109 <div className="cc"> 110 <div className="cc-head"> 111 <div className="cc-head-title"> 112 <span className="cc-dot" /> 113 ÐаÑÑоÑка кандидаÑа 114 </div> 115 <div className="cc-head-meta">пÑÐ¸Ð¼ÐµÑ Â· даннÑе обезлиÑенÑ</div> 116 </div> 117 118 <div className="cc-body"> 119 {/* Left identity column */} 120 <div className="cc-left"> 121 <div className="cc-photo"> 122 <image-slot 123 id={idPrefix + "-photo"} 124 shape="rounded" 125 radius="12" 126 placeholder="ÑоÑо" 127 ></image-slot> 128 </div> 129 130 <div className="cc-id"> 131 <div className="cc-name"> 132 {c.name} 133 <span className="cc-badge">пÑимеÑ</span> 134 </div> 135 <div className="cc-sub">{c.age} · {c.role}</div> 136 <span className="cc-status">{c.status}</span> 137 </div> 138 139 <div className="cc-facts"> 140 {c.facts.map(([k, v]) => ( 141 <div className="cc-fact" key={k}> 142 <span className="cc-fact-k">{k}</span> 143 <span className="cc-fact-v">{v}</span> 144 </div> 145 ))} 146 </div> 147 148 <div className="cc-links"> 149 {c.links.map((l) => ( 150 <a className="cc-link" key={l}>{l} âº</a> 151 ))} 152 </div> 153 154 <div className="cc-videos"> 155 <SectionLabel>Ðидео-инÑеÑвÑÑ</SectionLabel> 156 <div className="cc-vrow"> 157 <VideoTile /><VideoTile /><VideoTile /><VideoTile /> 158 </div> 159 </div> 160 </div> 161 162 {/* Right content column */} 163 <div className="cc-right"> 164 <section> 165 <SectionLabel>ХаÑакÑеÑиÑÑика ÑекÑÑÑеÑа</SectionLabel> 166 <div className="cc-stats3"> 167 {c.recruiterStats.map(([v, l]) => <Stat key={l} value={v} label={l} />)} 168 </div> 169 <p className="cc-para">{c.recruiterNote}</p> 170 </section> 171 172 <section className="cc-ai"> 173 <SectionLabel action="Ðо ÑÑанÑкÑипÑии инÑеÑвÑÑ">Ðнение ÐÐ-аÑÑиÑÑенÑа</SectionLabel> 174 <p className="cc-para">{c.aiNote}</p> 175 </section> 176 177 <section> 178 <SectionLabel>СопÑоводиÑелÑное пиÑÑмо</SectionLabel> 179 <p className="cc-quote">{c.cover}</p> 180 </section> 181 182 <div className="cc-resume"> 183 <section> 184 <SectionLabel>РезÑме · обÑазование</SectionLabel> 185 <div className="cc-edu"> 186 <div className="cc-edu-main">{c.education[0]}</div> 187 <div className="cc-edu-sub">{c.education[1]}</div> 188 <div className="cc-edu-year">{c.education[2]}</div> 189 </div> 190 </section> 191 192 <section> 193 <SectionLabel>РезÑме · опÑÑ ÑабоÑÑ</SectionLabel> 194 <div className="cc-stats3 cc-stats3--tight"> 195 {c.expStats.map(([v, l]) => <Stat key={l} value={v} label={l} />)} 196 </div> 197 <div className="cc-timeline"> 198 {c.experience.map((e, i) => ( 199 <div className="cc-exp" key={i}> 200 <div className="cc-exp-period">{e.period}</div> 201 <div className="cc-exp-body"> 202 <div className="cc-exp-title"> 203 <strong>{e.org}</strong> · {e.title} 204 </div> 205 <div className="cc-exp-desc">{e.desc}</div> 206 </div> 207 </div> 208 ))} 209 </div> 210 </section> 211 </div> 212 </div> 213 </div> 214 </div> 215 ); 216} 217 218Object.assign(window, { CandidateCard, VideoCircle, Stat, SectionLabel, CANDIDATE });
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.