Compare commits

...

16 Commits

12 changed files with 305 additions and 5 deletions

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
__pycache__/
*.pyc
.env
*.log
__pycache__/
*.pyc

140
README.md Normal file
View File

@@ -0,0 +1,140 @@
# InfraIT Landing + Admin
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> IT-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> Flask <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Telegram.
## <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> SEO-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, FAQ <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>.
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> SQLite (`data/infra.db`, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `leads`).
- <20><><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, SEO-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Telegram (bot token + chat id).
- Healthcheck-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (`/health`).
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Docker-<2D><><EFBFBD><EFBFBD> (`Dockerfile` + `docker-compose.yml`).
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- Python 3.12
- Flask 3.1
- Gunicorn 23
- SQLite
- HTML/CSS/JS (Jinja2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
```text
infraIT/
app.py
Dockerfile
docker-compose.yml
gunicorn_conf.py
requirements.txt
templates/
static/
data/
```
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `.env` (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> `.env.example`):
```env
SECRET_KEY=replace-with-a-long-random-string
```
`SECRET_KEY` <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>).
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> (Docker)
1. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `.env`:
```powershell
Copy-Item .env.example .env
```
2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
```powershell
docker compose up -d --build
```
3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
- <20><><EFBFBD><EFBFBD>: `http://localhost:4545`
- Healthcheck: `http://localhost:4545/health`
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
```powershell
docker compose down
```
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD> Docker)
```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
$env:SECRET_KEY = "your-strong-secret"
python app.py
```
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> `http://127.0.0.1:5000` (<28><><EFBFBD><EFBFBD><EFBFBD> Flask debug).
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- URL: `http://localhost:4545/admin/login` (<28><><EFBFBD> `http://127.0.0.1:5000/admin/login` <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
- <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>: `/admin/settings`
<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- canonical URL
- Yandex verification token
- ID <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.<2E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- Telegram Bot Token / Telegram Chat ID
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
### <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> `app.py` <20> `ADMIN_PASSWORD_HASH`.
<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
```powershell
python -c "from werkzeug.security import generate_password_hash; print(generate_password_hash('NEW_PASSWORD'))"
```
## Telegram-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Telegram:
1. <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `Telegram Bot Token`.
2. <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `Telegram Chat ID`.
3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Telegram <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD>: `data/infra.db`
- <20> Docker <20><><EFBFBD><EFBFBD><EFBFBD> `data/` <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> volume (`./data:/app/data`)
- <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: `static/img/infrait-logo.png`
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> `data/infra.db`.
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `SECRET_KEY`.
- <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `app.py` <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> `/admin/*` <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> reverse-proxy/VPN/IP allowlist.
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTTPS <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (Nginx/Caddy/Traefik).
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- `GET /` - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- `POST /` - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- `GET /admin/login` - <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- `GET/POST /admin/settings` - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- `GET /admin/logout` - <20><><EFBFBD><EFBFBD><EFBFBD>
- `GET /health` - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

Binary file not shown.

28
app.py
View File

@@ -7,7 +7,7 @@ from functools import wraps
from pathlib import Path
from urllib import parse, request as urllib_request
from flask import Flask, redirect, render_template, request, session, url_for
from flask import Flask, redirect, render_template, request, send_from_directory, session, url_for
from werkzeug.security import check_password_hash
@@ -27,6 +27,15 @@ DEFAULT_SETTINGS = {
"telegram_chat_id": "",
"geo_primary": "Казань и Татарстан — выезд в день запроса",
"geo_secondary": "Россия — удалённая поддержка",
"company_legal_name": "ООО «ИнфраИТ»",
"company_inn": "",
"company_kpp": "",
"company_ogrn": "",
"company_bank_name": "",
"company_bik": "",
"company_account": "",
"company_correspondent_account": "",
"company_legal_address": "",
}
app = Flask(__name__)
@@ -204,6 +213,12 @@ def index():
return render_template("index.html", success=success, error=error, settings=settings)
@app.route("/company-details")
def company_details():
settings = get_settings()
return render_template("company_details.html", settings=settings)
@app.route("/admin/login", methods=["GET", "POST"])
def admin_login():
error = None
@@ -250,6 +265,17 @@ def health():
return {"status": "error"}, 503
@app.route("/favicon.ico")
def favicon():
response = send_from_directory(
app.static_folder,
"img/favicon.png",
mimetype="image/png",
)
response.headers["Cache-Control"] = "no-store, max-age=0"
return response
if __name__ == "__main__":
init_db()
app.run(debug=True)

Binary file not shown.

BIN
static/img/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@@ -4,6 +4,9 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Вход в админку | InfraIT</title>
<link rel="icon" type="image/png" href="{{ url_for('favicon') }}">
<link rel="shortcut icon" href="{{ url_for('favicon') }}">
<link rel="apple-touch-icon" href="{{ url_for('favicon') }}">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Montserrat:wght@600;700;800&display=swap" rel="stylesheet">

View File

@@ -4,6 +4,9 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Настройки сайта | InfraIT</title>
<link rel="icon" type="image/png" href="{{ url_for('favicon') }}">
<link rel="shortcut icon" href="{{ url_for('favicon') }}">
<link rel="apple-touch-icon" href="{{ url_for('favicon') }}">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Montserrat:wght@600;700;800&display=swap" rel="stylesheet">
@@ -69,6 +72,45 @@
<input type="text" name="geo_secondary" value="{{ settings.geo_secondary }}">
</label>
<hr style="border:0;border-top:1px solid #d6e0ea;margin:6px 0 2px;">
<h3 style="margin:4px 0 2px;">Реквизиты компании</h3>
<label>Юридическое наименование
<input type="text" name="company_legal_name" value="{{ settings.company_legal_name }}">
</label>
<label>ИНН
<input type="text" name="company_inn" value="{{ settings.company_inn }}">
</label>
<label>КПП
<input type="text" name="company_kpp" value="{{ settings.company_kpp }}">
</label>
<label>ОГРН / ОГРНИП
<input type="text" name="company_ogrn" value="{{ settings.company_ogrn }}">
</label>
<label>Банк
<input type="text" name="company_bank_name" value="{{ settings.company_bank_name }}">
</label>
<label>БИК
<input type="text" name="company_bik" value="{{ settings.company_bik }}">
</label>
<label>Расчётный счёт
<input type="text" name="company_account" value="{{ settings.company_account }}">
</label>
<label>Корреспондентский счёт
<input type="text" name="company_correspondent_account" value="{{ settings.company_correspondent_account }}">
</label>
<label>Юридический адрес
<textarea name="company_legal_address" rows="3">{{ settings.company_legal_address }}</textarea>
</label>
<button type="submit" class="btn btn-primary">Сохранить настройки</button>
</form>
</div>

View File

@@ -11,6 +11,9 @@
<meta property="og:description" content="Компьютеры, серверы и сети для бизнеса без простоев. Татарстан и Казань с выездом, Россия удаленно.">
<meta property="og:type" content="website">
<meta property="og:locale" content="ru_RU">
<link rel="icon" type="image/png" href="{{ url_for('favicon') }}">
<link rel="shortcut icon" href="{{ url_for('favicon') }}">
<link rel="apple-touch-icon" href="{{ url_for('favicon') }}">
<meta name="yandex-verification" content="{{ settings.yandex_verification }}">
{% if settings.yandex_metrika_id %}
<script>

View File

@@ -0,0 +1,77 @@
{% extends "base.html" %}
{% block title %}{{ settings.company_name }} — Реквизиты компании{% endblock %}
{% block content %}
<header class="hero" id="top">
<div class="container">
<div class="topbar">
<a class="brand" href="{{ url_for('index') }}" aria-label="{{ settings.company_name }}">
<img src="{{ url_for('static', filename='img/infrait-logo.png') }}" alt="{{ settings.company_name }} logo" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline-flex';">
<span class="brand-fallback">{{ settings.company_name }}</span>
</a>
<nav class="nav">
<a href="{{ url_for('index') }}#services">Услуги</a>
<a href="{{ url_for('index') }}#pricing">Тарифы</a>
<a href="{{ url_for('index') }}#faq">FAQ</a>
<a href="{{ url_for('index') }}#contact">Контакты</a>
<a href="{{ url_for('company_details') }}">Реквизиты</a>
</nav>
<a href="tel:{{ settings.phone_link }}" class="phone">{{ settings.phone_display }}</a>
</div>
</div>
</header>
<main>
<section class="section">
<div class="container two-col">
<article class="panel">
<h2>Реквизиты компании</h2>
<p class="section-subtitle">Актуальные данные для договоров и бухгалтерских документов.</p>
<ul class="contacts">
<li><strong>Юридическое наименование:</strong> {{ settings.company_legal_name or "-" }}</li>
<li><strong>ИНН:</strong> {{ settings.company_inn or "-" }}</li>
<li><strong>КПП:</strong> {{ settings.company_kpp or "-" }}</li>
<li><strong>ОГРН / ОГРНИП:</strong> {{ settings.company_ogrn or "-" }}</li>
<li><strong>Банк:</strong> {{ settings.company_bank_name or "-" }}</li>
<li><strong>БИК:</strong> {{ settings.company_bik or "-" }}</li>
<li><strong>Расчётный счёт:</strong> {{ settings.company_account or "-" }}</li>
<li><strong>Корреспондентский счёт:</strong> {{ settings.company_correspondent_account or "-" }}</li>
<li><strong>Юридический адрес:</strong> {{ settings.company_legal_address or "-" }}</li>
</ul>
</article>
<article class="panel">
<h2>Контакты</h2>
<ul class="contacts">
<li><strong>Компания:</strong> {{ settings.company_name }}</li>
<li><strong>Телефон:</strong> <a href="tel:{{ settings.phone_link }}">{{ settings.phone_display }}</a></li>
<li><strong>Email:</strong> <a href="mailto:{{ settings.email }}">{{ settings.email }}</a></li>
<li><strong>Выезды:</strong> {{ settings.geo_primary }}</li>
<li><strong>По России:</strong> {{ settings.geo_secondary }}</li>
</ul>
<div class="cta-row">
<a href="{{ url_for('index') }}#contact" class="btn btn-primary">Оставить заявку</a>
<a href="{{ url_for('index') }}" class="btn btn-secondary">На главную</a>
</div>
</article>
</div>
</section>
</main>
<footer class="footer">
<div class="container footer-inner">
<div>
<a class="footer-logo" href="{{ url_for('index') }}" aria-label="{{ settings.company_name }}">
<img src="{{ url_for('static', filename='img/infrait-logo.png') }}" alt="{{ settings.company_name }} logo" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline-flex';">
<span class="brand-fallback">{{ settings.company_name }}</span>
</a>
<p>Комплексное IT-обслуживание бизнеса: компьютеры, серверы и сети.</p>
</div>
<div>
<p><a href="tel:{{ settings.phone_link }}">{{ settings.phone_display }}</a></p>
<p><a href="mailto:{{ settings.email }}">{{ settings.email }}</a></p>
</div>
</div>
</footer>
{% endblock %}

View File

@@ -1,6 +1,6 @@
{% extends "base.html" %}
{% block title %}{{ settings.company_name }} — IT-обслуживание бизнеса в Татарстане и по России{% endblock %}
{% block title %}{{ settings.company_name }} — IT-обслуживание бизнеса в Татарстанек и по России{% endblock %}
{% block head_extra %}
<script type="application/ld+json">
@@ -133,7 +133,7 @@
<article class="price-card">
<h3>Лайт</h3>
<p class="for">Для офисов 5-10 ПК</p>
<p class="price">от 2 500 ₽ / ПК</p>
<p class="price">от 2 000 ₽ / ПК</p>
<ul>
<li>Удалённая поддержка пользователей</li>
<li>Базовое администрирование сети</li>
@@ -333,6 +333,7 @@
<div>
<p><a href="tel:{{ settings.phone_link }}">{{ settings.phone_display }}</a></p>
<p><a href="mailto:{{ settings.email }}">{{ settings.email }}</a></p>
<p><a href="{{ url_for('company_details') }}">Реквизиты</a></p>
</div>
</div>
</footer>