PageSourceSearch

https://recruto.ru/candidate-card.jsx

js recruto.ru collected 2026-10-07 18:12:43 UTC 8,372 bytes, 218 lines download raw bytes

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.