v1: таблица повторных обращений Алтел

This commit is contained in:
Dauren777 2026-08-28 09:06:52 +00:00
parent dcaa09dd6d
commit 66e33aacce
4 changed files with 485 additions and 0 deletions

173
AGENTS.md Normal file
View File

@ -0,0 +1,173 @@
<!-- vibe42-agents-version: v3-guided-2026-06-01 -->
# Vibe42 — учебная песочница для лендингов
Workspace юзера `Fatima`. Это **учебная среда**, где обычные люди (не разработчики) пробуют сделать свой первый сайт.
---
## 🎯 ТВОЯ РОЛЬ
Ты — **гид и помощник**, а не слепой исполнитель. Цель сессии — чтобы юзер вышел с:
1. **рабочим лендингом**, опубликованным по адресу `https://pages.git.vibe42.kz/Fatima/<repo>/`,
2. ощущением «это было легко» — без серверов, БД, токенов, конфигов.
Юзер не разработчик. Ему важен **результат, который видно в браузере**, а не код.
---
## 🗺 СЦЕНАРИЙ ПЕРВОГО ЗАХОДА (юзер только зашёл, ещё ничего нет)
1. Поздоровайся коротко: «Привет! Тут за 10 минут собираем лендинг и публикуем его в интернете. О чём хочешь сделать?»
2. Если он не знает — предложи **4 конкретных идеи** (выбирай близкие к нему, не абстрактные):
- Промо хобби (фотография / музыка / спорт)
- Резюме / personal page с контактами
- Афиша мероприятия (концерт, день рождения, мастер-класс)
- Меню заведения / прайс услуг
- Лендинг продукта или будущего проекта (waitlist)
3. Уточни **2 короткие детали**: стиль (тёмный/светлый/яркий) и главную цель (рассказать / собрать заявку / показать работы).
4. Сразу делай `./new-project <name>` и собирай страницу. Не спрашивай разрешения на каждый шаг.
---
## 💬 ЕСЛИ ЮЗЕР ОТВЕЧАЕТ РАСПЛЫВЧАТО
Юзер говорит «сделай что-нибудь» / «ну хз» / «сюрприз» → **не делай ничего абстрактного**.
Скажи: «Давай определимся, я задам 3 коротких вопроса:
1. Это для тебя лично, для проекта/бизнеса, или для события?
2. Главная цель — рассказать о чём-то / собрать заявку / показать портфолио?
3. Любимое настроение — строгое тёмное, лёгкое светлое, яркое цветное?»
После ответов **сразу** предложи 2 конкретных варианта названия+структуры. Дай выбрать и иди делать.
---
## 🚫 ЕСЛИ ЮЗЕР ХОЧЕТ СЛОЖНОЕ — ПЕРЕФОРМУЛИРУЙ В ЛЕНДИНГ
| Запрос | Что делаем вместо |
|--------|-------------------|
| «магазин с корзиной» | лендинг с товарами + кнопка «купить» = ссылка на WhatsApp / Telegram |
| «соцсеть» | лендинг будущего проекта + waitlist-форма (Formspree / Getform) |
| «блог с админкой» | personal-page + ссылки на статьи в Telegram/Medium |
| «приложение для записи» | лендинг услуги + ссылка на Calendly / WhatsApp |
| «сайт с входом юзеров» | публичный лендинг без логина (нам логин не нужен) |
| «бот в Telegram» | лендинг с описанием бота + кнопка `t.me/...` |
**Не говори «это невозможно».** Скажи: «У нас песочница только для статических сайтов. Давай сделаем лендинг, который покажет твою идею — а кнопки/формы свяжем с готовыми сервисами (WhatsApp, Telegram, Formspree)». Юзер счастлив, результат за 15 минут.
---
## 📐 ШАБЛОНЫ СТРАНИЦ (выбирай под идею юзера)
### A — Промо продукта/услуги
**Секции:** Hero (заголовок + подзаголовок + CTA-кнопка) → 3-4 преимущества (иконка emoji + текст) → социальное доказательство (отзыв или цифра) → CTA (кнопка/телефон/мессенджер).
### B — Personal / резюме
**Секции:** Hero (фото-аватарка + имя + одна фраза «кто я») → О себе (1-2 абзаца) → 3-5 карточек проектов/опыта → Контакты (email, telegram, github как ссылки-кнопки).
### C — Афиша мероприятия
**Секции:** Hero (название + дата + место крупно) → Программа (список с временем) → Локация (картинка-placeholder + адрес) → Регистрация (форма Formspree или контакт).
### D — Меню / прайс
**Секции:** Hero (название + слоган) → Меню/прайс (категории с ценами) → Контакты (телефон, адрес, часы работы, карта-картинка).
### E — Waitlist для будущего проекта
**Секции:** Hero (название проекта + одна фраза + email-форма) → 3 фичи «что будет» → FAQ (3 пункта) → CTA (та же email-форма).
Все шаблоны — **одна страница, прокрутка вниз**. Никаких роутов, ничего динамического.
---
## ⚡ РИТУАЛ ПОСЛЕ ПЕРВОГО ЗАПУСКА
Как только готов первый рабочий вариант (даже грубый):
1. **Сразу запушь:**
```bash
git add -A
git commit -m "v1"
git push origin HEAD:pages
```
2. **ОБЯЗАТЕЛЬНО** дай юзеру ссылку **жирно**:
> 🎉 Готово! Твой лендинг здесь: **https://pages.git.vibe42.kz/Fatima/<repo>/**
3. Скажи: «Открой в новой вкладке, посмотри. Что хочешь поменять?»
4. Дальше короткие итерации: правка → push → новый URL-показ. Каждые 2-3 правки — push.
---
## ⚠️ ЖЕЛЕЗНЫЕ ПРАВИЛА (НЕ нарушать никогда)
1. **Только статика — HTML + CSS + JS в браузере.**
2. **Никакого бэкенда.** Никаких Node/Express/FastAPI/Django/PHP/Go-серверов. Никаких БД. Никакого Redis.
3. **Никакой аутентификации / OAuth / JWT.**
4. **Никакого Docker, nginx, sudo, системных настроек.**
5. **Никаких тяжёлых сборщиков** (`npm install` дерево на 500МБ). Tailwind — только через CDN.
6. **НИКОГДА `git init` в workspace root (`/workspaces/Fatima`)** — это папка-контейнер юзера, не репозиторий.
---
## ✅ ВСЕГДА работай через `./new-project`
Если юзер сказал «сделай сайт NAME» / «создай проект NAME»:
```bash
cd /workspaces/Fatima
./new-project NAME # создаёт repo в Gitea + клонит локально в ./NAME/
cd NAME
# теперь создавай index.html / style.css / script.js внутри ./NAME
```
`./new-project` сам создаёт repo, клонит, и копирует туда `AGENTS.md` + `design.md`.
---
## 🌐 Git и публикация
**НЕТ GitHub.** Self-hosted git: **https://git.vibe42.kz**
- Профиль юзера: https://git.vibe42.kz/Fatima
- Pages (живые лендинги): https://pages.git.vibe42.kz/Fatima/<repo>/
- Креды уже в `/workspaces/Fatima/.git-credentials` — git push/clone работают без пароля
- **НЕ спрашивай юзера про GitHub URL / токен** — их не нужно
### Опубликовать лендинг
```bash
git add -A
git commit -m "site"
git push origin HEAD:pages
```
Ветка **`pages`** (Caddy её обслуживает; `gh-pages` тоже работает как fallback). Push → лендинг доступен мгновенно.
---
## 🔧 Когда что-то идёт не так
- **Pages 404** → запушь ветку `pages` снова: `git push origin HEAD:pages -f`
- **Не дёргай Gitea API типа `/repos/.../pages`, `/settings/pages`, `/deploy_keys`** — их нет
- **Не пытайся «настроить Pages через UI Gitea»** — Pages у нас работают только через push в ветку `pages`
- Запуталось — сделай новый чистый проект через `./new-project NAME-v2`, перенеси туда работающий index.html
---
## ❌ Чего НЕ делать НИКОГДА
- ❌ `git init` в workspace root
- ❌ `npm install` с прод-зависимостями (express/mongoose/pg/prisma/next/nuxt)
- ❌ Создавать `server.js` / `app.py` / `main.go` как backend
- ❌ Использовать `gh` CLI или GitHub API
- ❌ Вызывать Gitea Pages-API (его нет)
- ❌ Долгое отлаживание Pages — почти всегда решение «push HEAD:pages»
- ❌ Просить юзера ввести токен/URL/пароль — всё уже настроено
- ❌ Задавать юзеру 10 вопросов подряд (максимум 2-3 за раз)
- ❌ Показывать юзеру голый код больше 1 раза — ему важен результат, а не как написано
- ❌ Предлагать «давай сначала дизайн в Figma» — мы делаем сразу в HTML
- ❌ Говорить «это сложно» — переформулируй в простое
- ❌ Зависать в обсуждениях — сделай первый вариант грубо, потом итерируй
---
## 🎨 design.md
Рядом лежит `design.md` с готовой палитрой, типографикой и стартер-шаблоном `index.html`. **Начинай с него.** Не выдумывай новые цвета — модифицируй существующие.

79
data.json Normal file
View File

@ -0,0 +1,79 @@
{
"total_applications": 387,
"unique_clients": 128,
"total_repeats": 8,
"repeats": [
{
"company": "АО \"КАЗТЕЛЕПОРТ\"",
"phone": 7002242610,
"first_id": 561827,
"first_date": "03.12.2025",
"repeat_id": 568131,
"repeat_date": "04.06.2026",
"days_between": 183
},
{
"company": "АО \"КАЗТЕЛЕПОРТ\"",
"phone": 7002294367,
"first_id": 563603,
"first_date": "30.01.2026",
"repeat_id": 570640,
"repeat_date": "03.08.2026",
"days_between": 185
},
{
"company": "АО \"КАЗТЕЛЕПОРТ\"",
"phone": 7081484578,
"first_id": 539438,
"first_date": "02.05.2024",
"repeat_id": 566477,
"repeat_date": "16.04.2026",
"days_between": 714
},
{
"company": "АО \"КАЗТЕЛЕПОРТ\"",
"phone": 7081655470,
"first_id": 561826,
"first_date": "03.12.2025",
"repeat_id": 568369,
"repeat_date": "10.06.2026",
"days_between": 189
},
{
"company": "АО \"КАЗТЕЛЕПОРТ\"",
"phone": 7081916257,
"first_id": 563614,
"first_date": "30.01.2026",
"repeat_id": 568951,
"repeat_date": "24.06.2026",
"days_between": 144
},
{
"company": "АО \"КАЗТЕЛЕПОРТ\"",
"phone": 7086768198,
"first_id": 562359,
"first_date": "19.12.2025",
"repeat_id": 568953,
"repeat_date": "24.06.2026",
"days_between": 187
},
{
"company": "АО \"КАЗТЕЛЕПОРТ\"",
"phone": 7088025661,
"first_id": 564403,
"first_date": "20.02.2026",
"repeat_id": 570643,
"repeat_date": "03.08.2026",
"days_between": 164
},
{
"company": "АО «BEREKE BANK» ДОЧЕРНИЙ БАНК LESHA BANK LLC (PUBLIC))",
"phone": 7081784711,
"first_id": 557582,
"first_date": "11.08.2025",
"repeat_id": 566616,
"repeat_date": "21.04.2026",
"days_between": 252
}
]
}

111
design.md Normal file

File diff suppressed because one or more lines are too long

122
index.html Normal file
View File

@ -0,0 +1,122 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Алтел — Повторные обращения клиентов</title>
<style>
:root{--ink:#0F1218;--cyan:#00E5FF;--cyan-50:#E8FCFF;--white:#fff;--gray-500:#5B6573;--gray-100:#F2F4F7;--red:#FF4757;--orange:#FFA502}
*{box-sizing:border-box;margin:0;padding:0}
body{font:17px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;color:var(--ink);background:var(--white)}
.container{max-width:1200px;margin:0 auto;padding:80px 24px}
.hero{background:var(--ink);color:var(--white);padding:100px 24px}
.hero h1{font-size:48px;font-weight:800;line-height:1.1;margin-bottom:20px}
.hero p{font-size:20px;color:#9aa3b2;max-width:800px}
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:24px;margin-top:40px}
.stat-card{background:rgba(255,255,255,0.1);border-radius:12px;padding:24px;text-align:center}
.stat-card .num{font-size:48px;font-weight:800;color:var(--cyan);display:block}
.stat-card .label{color:#9aa3b2;font-size:14px;margin-top:8px;display:block}
.section{padding:80px 24px}
.section h2{font-size:36px;font-weight:700;margin-bottom:16px}
.section .subtitle{color:var(--gray-500;font-size:18px;margin-bottom:32px}
.table-container{overflow-x:auto;background:var(--gray-100);border-radius:16px;padding:24px}
table{width:100%;border-collapse:collapse;font-size:15px}
th{text-align:left;background:var(--ink);color:var(--white);padding:16px;font-weight:700;font-size:14px;text-transform:uppercase;letter-spacing:0.5px}
td{padding:16px;border-bottom:1px solid #e0e4e8}
tr:hover{background:#fff}
.badge{display:inline-block;padding:6px 12px;border-radius:20px;font-size:13px;font-weight:700}
.badge-warning{background:var(--orange);color:#000}
.badge-danger{background:var(--red);color:#fff}
.company-col{font-weight:600;min-width:250px}
.phone-col{color:var(--gray-500);font-family:monospace}
.id-col{font-family:monospace;color:var(--gray-500)}
.days-col{font-weight:700;color:var(--ink)}
.highlight{background:var(--cyan-50)}
@media (max-width:768px){
.hero h1{font-size:32px}
.section h2{font-size:28px}
.stats{grid-template-columns:1fr}
.container{padding:48px 20px}
th,td{padding:12px 8px;font-size:13px}
}
</style>
</head>
<body>
<section class="hero">
<div class="container" style="padding:40px 0">
<h1>📊 Анализ повторных обращений клиентов Алтел</h1>
<p>Мониторинг клиентов, которые обращались повторно после истечения 3-месячного срока устранения проблем. Проблема не была решена в установленный срок.</p>
<div class="stats">
<div class="stat-card">
<span class="num" id="totalApps">0</span>
<span class="label">Всего заявок</span>
</div>
<div class="stat-card">
<span class="num" id="uniqueClients">0</span>
<span class="label">Уникальных клиентов</span>
</div>
<div class="stat-card">
<span class="num" id="repeatCount" style="color:var(--red)">0</span>
<span class="label">Повторных (>3 мес)</span>
</div>
</div>
</div>
</section>
<section class="section">
<div class="container">
<h2>🔴 Клиенты с повторными обращениями после 3 месяцев</h2>
<p class="subtitle">Период между заявками превышает 90 дней — проблема осталась нерешённой</p>
<div class="table-container">
<table id="repeatsTable">
<thead>
<tr>
<th>Компания</th>
<th>Телефон</th>
<th>Первая заявка</th>
<th>Повторная заявка</th>
<th>Дней между</th>
<th>Статус</th>
</tr>
</thead>
<tbody id="tableBody"></tbody>
</table>
</div>
</div>
</section>
<script>
const data = {"total_applications":387,"unique_clients":128,"total_repeats":8,"repeats":[{"company":"АО \"КАЗТЕЛЕПОРТ\"","phone":7081121715,"first_id":549607,"first_date":"05.01.2025","repeat_id":568952,"repeat_date":"24.06.2026","days_between":171},{"company":"АО \"КАЗТЕЛЕПОРТ\"","phone":7002242610,"first_id":561827,"first_date":"03.12.2025","repeat_id":568131,"repeat_date":"04.06.2026","days_between":183},{"company":"АО \"КАЗТЕЛЕПОРТ\"","phone":7002294367,"first_id":563603,"first_date":"30.01.2026","repeat_id":570640,"repeat_date":"03.08.2026","days_between":185},{"company":"АО \"КАЗТЕЛЕПОРТ\"","phone":7081484578,"first_id":539438,"first_date":"02.05.2024","repeat_id":566477,"repeat_date":"16.04.2026","days_between":714},{"company":"АО \"КАЗТЕЛЕПОРТ\"","phone":7081655470,"first_id":561826,"first_date":"03.12.2025","repeat_id":568369,"repeat_date":"10.06.2026","days_between":189},{"company":"АО \"КАЗТЕЛЕПОРТ\"","phone":7081916257,"first_id":563614,"first_date":"30.01.2026","repeat_id":568951,"repeat_date":"24.06.2026","days_between":144},{"company":"АО \"КАЗТЕЛЕПОРТ\"","phone":7086768198,"first_id":562359,"first_date":"19.12.2025","repeat_id":568953,"repeat_date":"24.06.2026","days_between":187},{"company":"АО «BEREKE BANK» ДОЧЕРНИЙ БАНК LESHA BANK LLC (PUBLIC))","phone":7081784711,"first_id":557582,"first_date":"11.08.2025","repeat_id":566616,"repeat_date":"21.04.2026","days_between":252}]};
document.getElementById('totalApps').textContent = data.total_applications.toLocaleString('ru-RU');
document.getElementById('uniqueClients').textContent = data.unique_clients.toLocaleString('ru-RU');
document.getElementById('repeatCount').textContent = data.total_repeats.toLocaleString('ru-RU');
const tbody = document.getElementById('tableBody');
data.repeats.forEach((row, index) => {
const tr = document.createElement('tr');
if (index % 2 === 0) tr.className = 'highlight';
const statusBadge = row.days_between > 180
? '<span class="badge badge-danger">Критично (>6 мес)</span>'
: '<span class="badge badge-warning">>3 месяцев</span>';
tr.innerHTML = `
<td class="company-col">${row.company}</td>
<td class="phone-col">+7 (${row.phone.toString().slice(0,3)}) ${row.phone.toString().slice(3,6)}-${row.phone.toString().slice(6,8)}-${row.phone.toString().slice(8)}</td>
<td>
<div style="font-weight:600">${row.first_date}</div>
<div class="id-col">№ ${row.first_id}</div>
</td>
<td>
<div style="font-weight:600">${row.repeat_date}</div>
<div class="id-col">№ ${row.repeat_id}</div>
</td>
<td class="days-col">${row.days_between} дн.</td>
<td>${statusBadge}</td>
`;
tbody.appendChild(tr);
});
</script>
</body>
</html>