first commit
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Административная панель заявок Анастасии Панкратенковой.">
|
||||
<title>Заявки — Анастасия Панкратенкова</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
|
||||
</head>
|
||||
<body class="admin-page admin-dashboard-page">
|
||||
<div class="admin-shell">
|
||||
<header class="admin-header">
|
||||
<a class="brand" href="{{ url_for('index') }}">
|
||||
<span class="brand-mark">АП</span>
|
||||
<span class="brand-name">Анастасия<br>Панкратенкова</span>
|
||||
</a>
|
||||
<div class="admin-header-actions">
|
||||
<span class="admin-status"><i></i> Вы вошли как администратор</span>
|
||||
<a class="admin-logout" href="{{ url_for('admin_logout') }}">Выйти <span>↗</span></a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="admin-main">
|
||||
<div class="admin-title-row">
|
||||
<div>
|
||||
<p class="eyebrow"><span class="eyebrow-dot"></span> Панель преподавателя</p>
|
||||
<h1>Ваши <em>заявки.</em></h1>
|
||||
</div>
|
||||
<div class="requests-count"><strong>{{ stats["total"] }}</strong><span>обращений<br>всего</span></div>
|
||||
</div>
|
||||
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
<div class="admin-flashes">
|
||||
{% for category, message in messages %}
|
||||
<div class="flash-message {{ category }}">{{ message }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<section class="admin-stats" aria-label="Статистика заявок">
|
||||
<div class="stat-card stat-card-total"><span>Всего</span><strong>{{ stats["total"] }}</strong><small>за всё время</small></div>
|
||||
<div class="stat-card"><span>Новые</span><strong>{{ stats["new"] }}</strong><small>ждут ответа</small></div>
|
||||
<div class="stat-card"><span>В работе</span><strong>{{ stats["contacted"] }}</strong><small>связались</small></div>
|
||||
<div class="stat-card"><span>Запланированы</span><strong>{{ stats["scheduled"] }}</strong><small>занятия</small></div>
|
||||
<div class="stat-card"><span>Завершены</span><strong>{{ stats["closed"] }}</strong><small>архив</small></div>
|
||||
</section>
|
||||
|
||||
<section class="admin-toolbar" aria-label="Фильтры заявок">
|
||||
<form class="admin-filters" action="{{ url_for('admin_dashboard') }}" method="get">
|
||||
<label class="filter-search"><span>Поиск</span><input type="search" name="q" value="{{ filters["q"] }}" placeholder="Имя, контакт или комментарий"></label>
|
||||
<label><span>Статус</span><select name="status"><option value="">Все статусы</option>{% for status_key, status_label in statuses.items() %}<option value="{{ status_key }}" {% if filters["status"] == status_key %}selected{% endif %}>{{ status_label }}</option>{% endfor %}</select></label>
|
||||
<label><span>Предмет</span><select name="subject"><option value="">Все предметы</option>{% for subject in subjects %}<option value="{{ subject }}" {% if filters["subject"] == subject %}selected{% endif %}>{{ subject }}</option>{% endfor %}</select></label>
|
||||
<button class="button button-primary filter-button" type="submit">Применить <span>↗</span></button>
|
||||
</form>
|
||||
<div class="toolbar-links">
|
||||
{% if filters["q"] or filters["status"] or filters["subject"] %}<a class="reset-filters" href="{{ url_for('admin_dashboard') }}">Сбросить фильтры</a>{% endif %}
|
||||
<a class="export-link" href="{{ url_for('admin_export', q=filters["q"], status=filters["status"], subject=filters["subject"]) }}">Скачать CSV <span>↓</span></a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% if consultation_requests %}
|
||||
<div class="results-heading"><span>Показано заявок: <strong>{{ consultation_requests|length }}</strong></span><span>Новые сверху</span></div>
|
||||
<section class="requests-list" aria-label="Список заявок">
|
||||
{% for consultation in consultation_requests %}
|
||||
<article class="request-card status-border-{{ consultation["status"] }}">
|
||||
<div class="request-card-head">
|
||||
<div class="request-card-head-left"><span class="status-badge status-{{ consultation["status"] }}">{{ statuses.get(consultation["status"], consultation["status"]) }}</span><span class="request-id">Заявка №{{ consultation["id"] }}</span></div>
|
||||
<time datetime="{{ consultation["created_at"] }}">{{ consultation["created_at"].replace("T", " · ") }}</time>
|
||||
</div>
|
||||
<div class="request-card-main">
|
||||
<div class="request-person"><h2>{{ consultation["name"] }}</h2><span>{{ consultation["contact"] }}</span></div>
|
||||
<dl class="request-meta">
|
||||
<div><dt>Предмет</dt><dd>{{ consultation["subject"] }}</dd></div>
|
||||
<div><dt>Экзамен</dt><dd>{{ consultation["exam"] }}</dd></div>
|
||||
<div><dt>Формат</dt><dd>{{ consultation["format"] }}</dd></div>
|
||||
<div><dt>Время</dt><dd>{{ consultation["preferred_time"] }}</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
{% if consultation["message"] %}<p class="request-message"><span>Комментарий</span>{{ consultation["message"] }}</p>{% endif %}
|
||||
<div class="request-actions">
|
||||
<form class="request-status-form" action="{{ url_for('admin_update_status', request_id=consultation["id"]) }}" method="post">
|
||||
<label for="status-{{ consultation["id"] }}">Статус</label>
|
||||
<select id="status-{{ consultation["id"] }}" name="status">{% for status_key, status_label in statuses.items() %}<option value="{{ status_key }}" {% if consultation["status"] == status_key %}selected{% endif %}>{{ status_label }}</option>{% endfor %}</select>
|
||||
<button class="mini-button" type="submit">Сохранить</button>
|
||||
</form>
|
||||
<details class="request-note" {% if consultation["admin_note"] %}open{% endif %}>
|
||||
<summary>{% if consultation["admin_note"] %}Изменить заметку{% else %}Добавить заметку{% endif %} <span>+</span></summary>
|
||||
<form action="{{ url_for('admin_update_note', request_id=consultation["id"]) }}" method="post">
|
||||
<textarea name="admin_note" rows="2" maxlength="2000" placeholder="Например: перезвонить вечером...">{{ consultation["admin_note"] }}</textarea>
|
||||
<button class="mini-button" type="submit">Сохранить заметку</button>
|
||||
</form>
|
||||
</details>
|
||||
<form class="request-delete-form" action="{{ url_for('admin_delete_request', request_id=consultation["id"]) }}" method="post" data-confirm="Удалить эту заявку? Восстановить её будет нельзя.">
|
||||
<button class="delete-button" type="submit">Удалить</button>
|
||||
</form>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% else %}
|
||||
<section class="empty-requests">
|
||||
<span>✦</span>
|
||||
<h2>{% if filters["q"] or filters["status"] or filters["subject"] %}Ничего не найдено.{% else %}Пока заявок нет.{% endif %}</h2>
|
||||
<p>{% if filters["q"] or filters["status"] or filters["subject"] %}Попробуйте изменить условия поиска или сбросить фильтры.{% else %}Новые обращения появятся здесь после заполнения формы на сайте.{% endif %}</p>
|
||||
{% if filters["q"] or filters["status"] or filters["subject"] %}<a class="button button-primary" href="{{ url_for('admin_dashboard') }}">Сбросить фильтры <span>↗</span></a>{% else %}<a class="button button-primary" href="{{ url_for('index') }}#contact">Посмотреть форму <span>↗</span></a>{% endif %}
|
||||
</section>
|
||||
{% endif %}
|
||||
</main>
|
||||
</div>
|
||||
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,35 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Вход для преподавателя — Анастасия Панкратенкова</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
|
||||
</head>
|
||||
<body class="admin-page">
|
||||
<main class="admin-login-card">
|
||||
<a class="brand admin-brand" href="{{ url_for('index') }}">
|
||||
<span class="brand-mark">АП</span>
|
||||
<span class="brand-name">Анастасия<br>Панкратенкова</span>
|
||||
</a>
|
||||
<div class="admin-login-heading">
|
||||
<p class="eyebrow"><span class="eyebrow-dot"></span> Приватный раздел</p>
|
||||
<h1>Заявки<br><em>на консультацию.</em></h1>
|
||||
<p>Введите пароль, чтобы посмотреть обращения учеников.</p>
|
||||
</div>
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="flash-message {{ category }}">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<form action="{{ url_for('admin_login') }}" method="post" class="admin-login-form">
|
||||
<label for="password">Пароль администратора</label>
|
||||
<input id="password" type="password" name="password" placeholder="Введите пароль" autocomplete="current-password" required autofocus>
|
||||
<button class="button button-primary form-button" type="submit">Войти в панель <span>↗</span></button>
|
||||
</form>
|
||||
<a class="admin-back-link" href="{{ url_for('index') }}">← Вернуться на сайт</a>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,163 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Подготовка к ОГЭ и ЕГЭ по математике и физике с Анастасией Панкратенковой.">
|
||||
<title>Анастасия Панкратенкова — математика и физика</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-shell">
|
||||
<header class="site-header">
|
||||
<a class="brand" href="#top" aria-label="На главную">
|
||||
<span class="brand-mark">АП</span>
|
||||
<span class="brand-name">Анастасия<br>Панкратенкова</span>
|
||||
</a>
|
||||
<nav class="main-nav" aria-label="Основная навигация">
|
||||
<a href="#about">О преподавателе</a>
|
||||
<a href="#subjects">Направления</a>
|
||||
<a href="#contact">Записаться</a>
|
||||
</nav>
|
||||
<a class="header-link" href="#contact">Консультация <span>↗</span></a>
|
||||
</header>
|
||||
|
||||
<main id="top">
|
||||
<section class="hero section-wrap">
|
||||
<div class="hero-copy">
|
||||
<p class="eyebrow"><span class="eyebrow-dot"></span> Математика · физика · подготовка к экзаменам</p>
|
||||
<h1>Понимать, решать, <em>быть уверенным.</em></h1>
|
||||
<p class="hero-lead">Помогаю школьникам увидеть логику точных наук и спокойно прийти к нужному результату на ОГЭ и ЕГЭ.</p>
|
||||
<div class="hero-actions">
|
||||
<a class="button button-primary" href="#contact">Записаться на консультацию <span>↗</span></a>
|
||||
<a class="text-link" href="#about">Познакомиться <span>↓</span></a>
|
||||
</div>
|
||||
<div class="hero-proof">
|
||||
<div class="proof-avatars" aria-hidden="true">
|
||||
<span>О</span><span>Е</span><span>+</span>
|
||||
</div>
|
||||
<p>Индивидуальный подход<br><strong>с 2017 года</strong></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hero-visual">
|
||||
<div class="hero-orbit orbit-one"></div>
|
||||
<div class="hero-orbit orbit-two"></div>
|
||||
<div class="hero-photo-frame">
|
||||
<img src="{{ url_for('static', filename='images/teacher.jpg') }}" alt="Анастасия Панкратенкова">
|
||||
</div>
|
||||
<div class="floating-note note-top"><span>∑</span><strong>Разбираем<br>до ясности</strong></div>
|
||||
<div class="floating-note note-bottom"><strong>2</strong><span>красных<br>диплома</span></div>
|
||||
<div class="math-scribble scribble-one">y = kx + b</div>
|
||||
<div class="math-scribble scribble-two">F = ma</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="ticker" aria-label="Ключевые направления">
|
||||
<div class="ticker-track">
|
||||
<span>Математика</span><i>✦</i><span>Физика</span><i>✦</i><span>ОГЭ</span><i>✦</i><span>ЕГЭ</span><i>✦</i><span>Математика</span><i>✦</i><span>Физика</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="about section-wrap section-grid" id="about">
|
||||
<div class="section-label"><span>01</span><span>О преподавателе</span></div>
|
||||
<div class="about-content">
|
||||
<div class="section-heading-row">
|
||||
<h2>Точные науки<br><em>могут быть понятными.</em></h2>
|
||||
<span class="round-arrow">↘</span>
|
||||
</div>
|
||||
<p class="section-intro">Я — Анастасия Викторовна, преподаватель математики и физики. На занятиях мы не заучиваем решения, а разбираемся, как всё устроено — шаг за шагом и в удобном для ученика темпе.</p>
|
||||
<div class="about-details">
|
||||
<div class="detail-item"><span class="detail-number">01</span><p><strong>Образование</strong>АГУ, бакалавриат «Математика» и магистратура «Математическое образование».</p></div>
|
||||
<div class="detail-item"><span class="detail-number">02</span><p><strong>Результат</strong>Обе ступени образования окончены с красным дипломом.</p></div>
|
||||
<div class="detail-item"><span class="detail-number">03</span><p><strong>Опыт</strong>Официально веду педагогическую деятельность с 2017 года.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="subjects section-wrap" id="subjects">
|
||||
<div class="section-label"><span>02</span><span>Направления</span></div>
|
||||
<div class="subjects-heading">
|
||||
<h2>Выберите свою<br><em>точку старта.</em></h2>
|
||||
<p>Первая консультация помогает определить текущий уровень, цели и комфортный план подготовки.</p>
|
||||
</div>
|
||||
<div class="subject-cards">
|
||||
<article class="subject-card subject-card-dark">
|
||||
<div class="card-top"><span class="card-number">01</span><span class="card-icon">∑</span></div>
|
||||
<div><p class="card-kicker">Подготовка</p><h3>Математика</h3><p class="card-description">От уверенной базы до сложных задач второй части. Разбираем теорию, практику и стратегию экзамена.</p></div>
|
||||
<a href="#contact" class="card-link">Обсудить подготовку <span>↗</span></a>
|
||||
</article>
|
||||
<article class="subject-card subject-card-accent">
|
||||
<div class="card-top"><span class="card-number">02</span><span class="card-icon">F</span></div>
|
||||
<div><p class="card-kicker">Подготовка</p><h3>Физика</h3><p class="card-description">Учимся видеть физику за формулами: решаем задачи, выстраиваем связи и готовимся к нужному баллу.</p></div>
|
||||
<a href="#contact" class="card-link">Обсудить подготовку <span>↗</span></a>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="process section-wrap">
|
||||
<div class="section-label"><span>03</span><span>Как проходят занятия</span></div>
|
||||
<div class="process-content">
|
||||
<h2>Спокойная подготовка<br><em>с понятным маршрутом.</em></h2>
|
||||
<div class="process-list">
|
||||
<div class="process-item"><span>01</span><div><h3>Знакомимся с задачей</h3><p>Определяем цель, уровень знаний и точки, которые требуют внимания.</p></div><b>↗</b></div>
|
||||
<div class="process-item"><span>02</span><div><h3>Собираем систему</h3><p>Выстраиваем понятную теорию и закрепляем её практикой на реальных заданиях.</p></div><b>↗</b></div>
|
||||
<div class="process-item"><span>03</span><div><h3>Двигаемся к результату</h3><p>Отслеживаем прогресс, разбираем ошибки и учимся уверенно работать на экзамене.</p></div><b>↗</b></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="education section-wrap">
|
||||
<div class="education-card">
|
||||
<div class="education-mark">✦</div>
|
||||
<div><p class="card-kicker">Образование</p><h2>Два диплома.<br><em>Одна цель.</em></h2></div>
|
||||
<div class="education-years"><span>2013</span><i></i><span>2019</span></div>
|
||||
<div class="education-copy"><p>АГУ · бакалавриат<br>«Математика»</p><p>АГУ · магистратура<br>«Математическое образование»</p></div>
|
||||
<div class="red-diploma">Красный диплом <span>× 2</span></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="contact section-wrap" id="contact">
|
||||
<div class="contact-intro">
|
||||
<div class="section-label"><span>04</span><span>Первый шаг</span></div>
|
||||
<h2>Давайте<br><em>познакомимся.</em></h2>
|
||||
<p>Оставьте заявку — я свяжусь с вами, отвечу на вопросы и помогу выбрать формат подготовки.</p>
|
||||
<div class="contact-sign">Анастасия <span>Панкратенкова</span></div>
|
||||
</div>
|
||||
<div class="form-card">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="flash-message {{ category }}">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<form action="{{ url_for('submit_request') }}" method="post">
|
||||
<div class="form-row">
|
||||
<label>Ваше имя <span>*</span><input type="text" name="name" placeholder="Например, Мария" required></label>
|
||||
<label>Как связаться <span>*</span><input type="text" name="contact" placeholder="Телефон или Telegram" required></label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>Предмет <span>*</span><select name="subject" required><option value="" disabled selected>Выберите предмет</option><option value="math">Математика</option><option value="physics">Физика</option></select></label>
|
||||
<label>Экзамен <span>*</span><select name="exam" required><option value="" disabled selected>Выберите экзамен</option><option value="oge">ОГЭ</option><option value="ege">ЕГЭ</option><option value="other">Пока не определились</option></select></label>
|
||||
</div>
|
||||
<div class="form-row form-row-wide">
|
||||
<label>Желаемое время занятий <span>*</span><select name="preferred_time" required><option value="" disabled selected>Когда вам удобнее?</option><option value="morning">Утро</option><option value="day">День</option><option value="evening">Вечер</option><option value="flexible">Готовы обсудить</option></select></label>
|
||||
</div>
|
||||
<fieldset class="format-field"><legend>Формат занятий <span>*</span></legend><div class="radio-options"><label><input type="radio" name="format" value="online" required><span>Онлайн</span></label><label><input type="radio" name="format" value="offline"><span>Очно</span></label><label><input type="radio" name="format" value="other"><span>Не знаю</span></label></div></fieldset>
|
||||
<label>Комментарий <span class="optional">необязательно</span><textarea name="message" rows="3" placeholder="Расскажите, какая цель у занятий..."></textarea></label>
|
||||
<button class="button button-primary form-button" type="submit">Отправить заявку <span>↗</span></button>
|
||||
<p class="form-note">Нажимая кнопку, вы соглашаетесь на обработку персональных данных.</p>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer class="site-footer section-wrap">
|
||||
<a class="brand" href="#top"><span class="brand-mark">АП</span><span class="brand-name">Анастасия<br>Панкратенкова</span></a>
|
||||
<p>Математика и физика<br>с пониманием.</p>
|
||||
<span>© {{ current_year }}</span>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Заявка отправлена — Анастасия Панкратенкова</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
|
||||
</head>
|
||||
<body class="success-page">
|
||||
<main class="success-card">
|
||||
<span class="success-symbol">✓</span>
|
||||
<p class="eyebrow"><span class="eyebrow-dot"></span> Заявка отправлена</p>
|
||||
<h1>Спасибо, {{ name or "что написали" }}!</h1>
|
||||
<p>Анастасия свяжется с вами в ближайшее время, чтобы обсудить цель, формат и удобное время занятий.</p>
|
||||
<a class="button button-primary" href="{{ url_for('index') }}">Вернуться на сайт <span>↗</span></a>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user