feat: Update styles and layout for improved UI/UX; add GEMINI project documentation
This commit is contained in:
72
.vscode/ftp-kr.sync.cache.json
vendored
72
.vscode/ftp-kr.sync.cache.json
vendored
@@ -144,8 +144,8 @@
|
||||
},
|
||||
"CRON.md": {
|
||||
"type": "-",
|
||||
"size": 4784,
|
||||
"lmtime": 1771620216534,
|
||||
"size": 4875,
|
||||
"lmtime": 1771669072264,
|
||||
"modified": false
|
||||
},
|
||||
"DATABASE.md": {
|
||||
@@ -169,8 +169,8 @@
|
||||
},
|
||||
".env.example": {
|
||||
"type": "-",
|
||||
"size": 442,
|
||||
"lmtime": 1771626490188,
|
||||
"size": 616,
|
||||
"lmtime": 1771669059812,
|
||||
"modified": false
|
||||
},
|
||||
".htaccess": {
|
||||
@@ -245,6 +245,12 @@
|
||||
"size": 829,
|
||||
"lmtime": 1771620035555,
|
||||
"modified": false
|
||||
},
|
||||
"010_dataforseo_indexed_pages.sql": {
|
||||
"type": "-",
|
||||
"size": 238,
|
||||
"lmtime": 1771668925563,
|
||||
"modified": false
|
||||
}
|
||||
},
|
||||
"src": {
|
||||
@@ -299,14 +305,14 @@
|
||||
},
|
||||
"SettingsController.php": {
|
||||
"type": "-",
|
||||
"size": 1868,
|
||||
"lmtime": 1771626466574,
|
||||
"size": 2267,
|
||||
"lmtime": 1771668989725,
|
||||
"modified": false
|
||||
},
|
||||
"SiteController.php": {
|
||||
"type": "-",
|
||||
"size": 16907,
|
||||
"lmtime": 1771628191087,
|
||||
"size": 17063,
|
||||
"lmtime": 1771668985080,
|
||||
"modified": false
|
||||
},
|
||||
"TopicController.php": {
|
||||
@@ -395,14 +401,14 @@
|
||||
},
|
||||
"Site.php": {
|
||||
"type": "-",
|
||||
"size": 1441,
|
||||
"lmtime": 1771627194103,
|
||||
"size": 1668,
|
||||
"lmtime": 1771669773477,
|
||||
"modified": false
|
||||
},
|
||||
"SiteSeoMetric.php": {
|
||||
"type": "-",
|
||||
"size": 4817,
|
||||
"lmtime": 1771627676032,
|
||||
"size": 6296,
|
||||
"lmtime": 1771669766557,
|
||||
"modified": false
|
||||
},
|
||||
"Topic.php": {
|
||||
@@ -419,6 +425,12 @@
|
||||
}
|
||||
},
|
||||
"Services": {
|
||||
"DataForSeoService.php": {
|
||||
"type": "-",
|
||||
"size": 3670,
|
||||
"lmtime": 1771668941654,
|
||||
"modified": false
|
||||
},
|
||||
"FtpService.php": {
|
||||
"type": "-",
|
||||
"size": 7464,
|
||||
@@ -457,8 +469,8 @@
|
||||
},
|
||||
"SiteSeoSyncService.php": {
|
||||
"type": "-",
|
||||
"size": 3146,
|
||||
"lmtime": 1771620084332,
|
||||
"size": 6697,
|
||||
"lmtime": 1771669807579,
|
||||
"modified": false
|
||||
},
|
||||
"TopicBalancer.php": {
|
||||
@@ -561,8 +573,8 @@
|
||||
},
|
||||
"seo-stats.php": {
|
||||
"type": "-",
|
||||
"size": 7955,
|
||||
"lmtime": 1771627707865,
|
||||
"size": 8683,
|
||||
"lmtime": 1771669055520,
|
||||
"modified": false
|
||||
}
|
||||
},
|
||||
@@ -605,16 +617,16 @@
|
||||
"settings": {
|
||||
"index.php": {
|
||||
"type": "-",
|
||||
"size": 7022,
|
||||
"lmtime": 1771626482753,
|
||||
"size": 9423,
|
||||
"lmtime": 1771669002362,
|
||||
"modified": false
|
||||
}
|
||||
},
|
||||
"sites": {
|
||||
"create.php": {
|
||||
"type": "-",
|
||||
"size": 5295,
|
||||
"lmtime": 1771620136407,
|
||||
"size": 5744,
|
||||
"lmtime": 1771669030881,
|
||||
"modified": false
|
||||
},
|
||||
"dashboard.php": {
|
||||
@@ -625,8 +637,8 @@
|
||||
},
|
||||
"edit.php": {
|
||||
"type": "-",
|
||||
"size": 13837,
|
||||
"lmtime": 1771628695879,
|
||||
"size": 14374,
|
||||
"lmtime": 1771669040355,
|
||||
"modified": false
|
||||
},
|
||||
"index.php": {
|
||||
@@ -637,8 +649,8 @@
|
||||
},
|
||||
"seo.php": {
|
||||
"type": "-",
|
||||
"size": 7545,
|
||||
"lmtime": 1771626686595,
|
||||
"size": 8656,
|
||||
"lmtime": 1771669504439,
|
||||
"modified": false
|
||||
}
|
||||
},
|
||||
@@ -665,6 +677,12 @@
|
||||
"lmtime": 1771626947881,
|
||||
"modified": false
|
||||
},
|
||||
"tmp_semstorm_test.php": {
|
||||
"type": "-",
|
||||
"size": 1027,
|
||||
"lmtime": 1771627094790,
|
||||
"modified": false
|
||||
},
|
||||
"TODO.md": {
|
||||
"type": "-",
|
||||
"size": 233,
|
||||
@@ -792,12 +810,6 @@
|
||||
"lmtime": 1771150407034,
|
||||
"modified": false
|
||||
}
|
||||
},
|
||||
"tmp_semstorm_test.php": {
|
||||
"type": "-",
|
||||
"size": 1027,
|
||||
"lmtime": 1771627094790,
|
||||
"modified": false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
85
GEMINI.md
Normal file
85
GEMINI.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# GEMINI.md - BackPRO (SEO Management System)
|
||||
|
||||
## Project Overview
|
||||
**BackPRO** is a custom PHP-based SEO management system designed to automate the management and content generation for a network of WordPress satellite sites. It leverages the WordPress REST API, OpenAI for content generation, and various image APIs (like Freepik) to create and publish SEO-optimized articles.
|
||||
|
||||
### Core Technologies
|
||||
- **Language:** PHP 8.3+ (Strict Types enabled)
|
||||
- **Framework:** Custom MVC architecture (no external framework like Laravel/Symfony)
|
||||
- **Database:** MySQL/MariaDB (via PDO)
|
||||
- **Frontend:** Bootstrap 5, Vanilla CSS/JS, PHP Templates
|
||||
- **Integrations:**
|
||||
- WordPress REST API (via Application Passwords)
|
||||
- OpenAI API (GPT models for content)
|
||||
- Freepik/Unsplash/Pexels APIs (for images)
|
||||
- Semstorm/DataForSeo (for SEO metrics)
|
||||
- **Dependencies:** Managed via Composer (`guzzlehttp/guzzle`, `phpdotenv`)
|
||||
|
||||
---
|
||||
|
||||
## Architecture & Structure
|
||||
|
||||
The project follows a standard MVC pattern with a clear separation of concerns:
|
||||
|
||||
- **`index.php`**: Front Controller - entry point for all web requests.
|
||||
- **`src/Core/`**: The "engine" of the application.
|
||||
- `App.php`: Application bootstrapper.
|
||||
- `Router.php`: Maps URLs to controllers (defined in `config/routes.php`).
|
||||
- `Model.php`: Base class for database interactions using PDO.
|
||||
- `Controller.php`: Base class for all controllers.
|
||||
- `Auth.php`: Session-based authentication system.
|
||||
- **`src/Controllers/`**: Contains application logic (Auth, Dashboard, Sites, Topics, Articles, etc.).
|
||||
- **`src/Models/`**: Database entity representations.
|
||||
- **`src/Services/`**: External API clients and complex business logic (e.g., `WordPressService`, `OpenAIService`, `PublisherService`).
|
||||
- **`templates/`**: PHP-based view templates.
|
||||
- **`cron/`**: Scripts designed for CLI execution via system cron jobs (automated publishing).
|
||||
- **`migrations/`**: SQL files for database schema evolution.
|
||||
|
||||
---
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
### 1. Coding Standards
|
||||
- **Naming:** Follow PSR-4 for class autoloading (Namespace `App\` maps to `src/`).
|
||||
- **Database:** Always use Prepared Statements via `src/Core/Database.php` or `src/Core/Model.php` to prevent SQL Injection.
|
||||
- **Security:**
|
||||
- Use `htmlspecialchars()` in templates for XSS protection.
|
||||
- Passwords must be hashed using `bcrypt` (via `password_hash`).
|
||||
- API keys and sensitive data belong in the `.env` file.
|
||||
- **Error Handling:** Use `App\Helpers\Logger` for logging application events and errors. Logs are stored in `storage/logs/`.
|
||||
|
||||
### 2. Working with Models
|
||||
Models extend `App\Core\Model` and should contain methods for specific data retrieval. Use `$this->db` (a PDO instance) for queries.
|
||||
|
||||
### 3. Adding Routes
|
||||
New endpoints must be registered in `config/routes.php`. Format: `$router->METHOD('/path', 'ControllerName', 'methodName')`.
|
||||
|
||||
### 4. Integration Logic
|
||||
Place logic for interacting with external services in the `src/Services/` directory. These should be designed as reusable components.
|
||||
|
||||
---
|
||||
|
||||
## Deployment & Running
|
||||
|
||||
### Environment Setup
|
||||
1. **PHP:** Ensure PHP 8.1+ is installed.
|
||||
2. **Composer:** Run `composer install` to install dependencies.
|
||||
3. **Configuration:** Copy `.env.example` to `.env` and fill in:
|
||||
- Database credentials (`DB_HOST`, `DB_NAME`, `DB_USER`, `DB_PASS`)
|
||||
- API Keys (`OPENAI_API_KEY`, `FREEPIK_API_KEY`, etc.)
|
||||
4. **Database:** Execute SQL scripts from the `migrations/` directory in order.
|
||||
|
||||
### Commands & Scripts
|
||||
- **Web Interface:** Accessible via a web server pointing to the root directory (ensure `.htaccess` is respected).
|
||||
- **Automation (CRON):**
|
||||
- `php cron/publish.php` - Triggers the automated publishing cycle.
|
||||
- `php cron/semstorm.php` - Syncs SEO metrics.
|
||||
|
||||
---
|
||||
|
||||
## Key Features
|
||||
- **WordPress Site CRUD:** Add and manage WP instances.
|
||||
- **Topic Balancer:** Ensures content is distributed evenly across assigned topics.
|
||||
- **AI Content Engine:** Generates unique articles with contextual images.
|
||||
- **Remote Installer:** Automates the installation of WordPress and themes on remote servers.
|
||||
- **SEO Analytics:** Tracks visibility and indexing status via third-party services.
|
||||
@@ -1,111 +1,172 @@
|
||||
/* BackPRO - Custom Styles */
|
||||
/* BackPRO - Compact Modern Dashboard Styles */
|
||||
|
||||
:root {
|
||||
--primary-color: #4f46e5;
|
||||
--primary-hover: #4338ca;
|
||||
--bg-main: #f8fafc;
|
||||
--sidebar-bg: #0f172a;
|
||||
--sidebar-link: #94a3b8;
|
||||
--sidebar-link-active: #ffffff;
|
||||
--sidebar-link-hover: #1e293b;
|
||||
--card-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||
--border-color: #e2e8f0;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #f4f6f9;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
background-color: var(--bg-main);
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-size: 0.875rem; /* Zmniejszona baza (14px zamiast 16px) */
|
||||
color: #1e293b;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
/* Global Links */
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
text-decoration: none;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--primary-hover);
|
||||
}
|
||||
|
||||
/* Sidebar - Compact */
|
||||
.sidebar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
background-color: var(--sidebar-bg);
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.05);
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.content-area {
|
||||
min-width: 0;
|
||||
.sidebar-header {
|
||||
padding: 1rem 1.25rem; /* Zmniejszony padding */
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.sidebar .nav-link {
|
||||
padding: 0.6rem 1rem;
|
||||
color: var(--sidebar-link);
|
||||
padding: 0.5rem 1rem; /* Zmniejszony padding */
|
||||
margin: 0.15rem 0.75rem; /* Mniejsze marginesy */
|
||||
border-radius: 0.375rem;
|
||||
margin: 0.1rem 0;
|
||||
transition: background-color 0.2s;
|
||||
font-weight: 500;
|
||||
font-size: 0.85rem; /* Mniejsza czcionka */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.sidebar .nav-link:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
.sidebar .nav-link i {
|
||||
font-size: 1rem;
|
||||
margin-right: 0.75rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active {
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
/* Header - Slim */
|
||||
header {
|
||||
background-color: rgba(255, 255, 255, 0.8) !important;
|
||||
backdrop-filter: blur(8px);
|
||||
border-bottom: 1px solid var(--border-color) !important;
|
||||
padding: 0.5rem 1.25rem !important; /* Odchudzony header */
|
||||
}
|
||||
|
||||
header h5 {
|
||||
font-size: 1rem; /* Mniejszy tytuł */
|
||||
}
|
||||
|
||||
/* Cards - Compact */
|
||||
.card {
|
||||
border: none;
|
||||
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
background-color: #ffffff;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: var(--card-shadow);
|
||||
}
|
||||
|
||||
.table th {
|
||||
.card-header {
|
||||
padding: 0.75rem 1rem; /* Mniejszy padding */
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
/* Tables - High Density */
|
||||
.table-container {
|
||||
background: #fff;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.table thead th {
|
||||
background-color: #f8fafc;
|
||||
color: #64748b;
|
||||
font-weight: 600;
|
||||
font-size: 0.85rem;
|
||||
text-transform: uppercase;
|
||||
color: #6c757d;
|
||||
border-bottom-width: 1px;
|
||||
font-size: 0.7rem; /* Bardzo mały, czytelny label */
|
||||
letter-spacing: 0.05em;
|
||||
padding: 0.6rem 0.85rem; /* Ciasne komórki */
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.article-content h2 {
|
||||
font-size: 1.4rem;
|
||||
margin-top: 1.5rem;
|
||||
.table tbody td {
|
||||
padding: 0.6rem 0.85rem; /* Ciasne komórki */
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.article-content h3 {
|
||||
font-size: 1.2rem;
|
||||
margin-top: 1.2rem;
|
||||
/* Stats Cards - Compact */
|
||||
.stat-card {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.article-content p {
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.article-content,
|
||||
.article-content * {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.btn-group .btn + form .btn {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.bp-toast-container {
|
||||
z-index: 2000;
|
||||
max-width: 420px;
|
||||
}
|
||||
|
||||
.bp-toast {
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.bp-toast .toast-body {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.bp-toast.text-bg-warning .btn-close {
|
||||
filter: none;
|
||||
}
|
||||
|
||||
.bp-toast-fallback {
|
||||
margin-bottom: 0.5rem;
|
||||
padding: 0.75rem 0.95rem;
|
||||
border-radius: 10px;
|
||||
background: #1f2a44;
|
||||
color: #fff;
|
||||
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.bp-confirm-modal .modal-content {
|
||||
border: 0;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 1rem 2rem rgba(19, 31, 56, 0.2);
|
||||
}
|
||||
|
||||
.bp-confirm-modal .modal-title {
|
||||
.stat-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 1.25rem; /* Mniejsza wartość */
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.bp-confirm-modal .modal-body p {
|
||||
color: #445066;
|
||||
line-height: 1.5;
|
||||
.stat-label {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
/* Badges - Small */
|
||||
.badge {
|
||||
padding: 0.25em 0.6em;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Buttons - Slim */
|
||||
.btn {
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.35rem 0.75rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
padding: 0.2rem 0.5rem;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
/* Main Content Padding */
|
||||
main.p-4 {
|
||||
padding: 1.25rem !important; /* Mniejszy margines główny */
|
||||
}
|
||||
|
||||
/* Forms - Compact */
|
||||
.form-control, .form-select {
|
||||
padding: 0.4rem 0.6rem;
|
||||
font-size: 0.875rem;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.article-content {
|
||||
font-size: 0.95rem; /* Nieco mniejszy tekst artykułu */
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
@@ -67,4 +67,13 @@ class Router
|
||||
http_response_code(404);
|
||||
echo '<h1>404 - Strona nie znaleziona</h1>';
|
||||
}
|
||||
|
||||
public static function isCurrent(string $path): bool
|
||||
{
|
||||
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
||||
$uri = rtrim($uri, '/') ?: '/';
|
||||
$path = rtrim($path, '/') ?: '/';
|
||||
|
||||
return $uri === $path;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
<header class="bg-white border-bottom p-3 d-flex justify-content-between align-items-center">
|
||||
<div></div>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<form method="post" action="/publish/run" class="d-inline" data-confirm="Uruchomic publikacje teraz?">
|
||||
<button type="submit" class="btn btn-sm btn-success">
|
||||
<i class="bi bi-play-circle me-1"></i>Publikuj teraz
|
||||
<div class="d-flex align-items-center">
|
||||
<!-- Można tu dodać tytuł strony w zależności od routera -->
|
||||
<h5 class="mb-0 fw-semibold text-secondary px-2">Panel Sterowania</h5>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-3 pe-2">
|
||||
<form method="post" action="/publish/run" class="d-inline" data-confirm="Uruchomić publikację teraz?">
|
||||
<button type="submit" class="btn btn-sm btn-primary shadow-sm px-3">
|
||||
<i class="bi bi-play-circle-fill me-1"></i> Uruchom Publikację
|
||||
</button>
|
||||
</form>
|
||||
<a href="/logout" class="btn btn-sm btn-outline-secondary">
|
||||
<i class="bi bi-box-arrow-right me-1"></i>Wyloguj
|
||||
</a>
|
||||
<div class="border-start ms-2 ps-3 d-flex align-items-center">
|
||||
<a href="/settings" class="btn btn-sm btn-outline-secondary border-0 px-2" title="Ustawienia">
|
||||
<i class="bi bi-gear fs-5"></i>
|
||||
</a>
|
||||
<a href="/logout" class="btn btn-sm btn-outline-danger border-0 px-2" title="Wyloguj">
|
||||
<i class="bi bi-power fs-5"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -4,26 +4,31 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BackPRO - Zarządzanie Zapleczem SEO</title>
|
||||
<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=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
|
||||
<link href="/assets/css/app.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<body class="bg-light-subtle">
|
||||
<?php if (\App\Core\Auth::check()): ?>
|
||||
<div class="d-flex">
|
||||
<div class="d-flex min-vh-100">
|
||||
<?php require __DIR__ . '/sidebar.php'; ?>
|
||||
<div class="flex-grow-1 content-area">
|
||||
<div class="flex-grow-1 d-flex flex-column content-area">
|
||||
<?php require __DIR__ . '/header.php'; ?>
|
||||
<main class="p-4">
|
||||
<?php if (!empty($flashMessages)): ?>
|
||||
<?php foreach ($flashMessages as $flash): ?>
|
||||
<div class="alert alert-<?= htmlspecialchars($flash['type']) ?> alert-dismissible fade show">
|
||||
<?= htmlspecialchars($flash['message']) ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
<?= $content ?>
|
||||
<main class="p-4 flex-grow-1">
|
||||
<div class="container-fluid p-0">
|
||||
<?php if (!empty($flashMessages)): ?>
|
||||
<?php foreach ($flashMessages as $flash): ?>
|
||||
<div class="alert alert-<?= htmlspecialchars($flash['type']) ?> alert-dismissible fade show shadow-sm border-0">
|
||||
<?= htmlspecialchars($flash['message']) ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
<?= $content ?>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,53 +1,81 @@
|
||||
<nav class="sidebar bg-dark text-white d-flex flex-column flex-shrink-0" style="width: 250px; min-height: 100vh;">
|
||||
<div class="p-3 border-bottom border-secondary">
|
||||
<h5 class="mb-0"><i class="bi bi-globe2"></i> BackPRO</h5>
|
||||
<small class="text-secondary">Zarządzanie Zapleczem SEO</small>
|
||||
<nav class="sidebar d-flex flex-column flex-shrink-0 min-vh-100" style="width: 260px;">
|
||||
<div class="sidebar-header">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="bg-primary rounded-3 p-2 me-3 shadow-sm">
|
||||
<i class="bi bi-rocket-takeoff-fill text-white fs-4"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h5 class="mb-0 text-white fw-bold tracking-tight">BackPRO</h5>
|
||||
<p class="text-secondary small mb-0" style="font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;">SEO Engine</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="nav flex-column p-2 flex-grow-1">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-white" href="/">
|
||||
<i class="bi bi-speedometer2 me-2"></i>Dashboard
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-white" href="/sites">
|
||||
<i class="bi bi-wordpress me-2"></i>Strony
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-white" href="/seo/stats">
|
||||
<i class="bi bi-graph-up-arrow me-2"></i>Statystyki SEO
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-white" href="/global-topics">
|
||||
<i class="bi bi-bookmarks me-2"></i>Tematy
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-white" href="/articles">
|
||||
<i class="bi bi-file-earmark-text me-2"></i>Artykuły
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-white" href="/logs">
|
||||
<i class="bi bi-journal-text me-2"></i>Log
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-white" href="/installer">
|
||||
<i class="bi bi-cloud-upload me-2"></i>Instalator WP
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-white" href="/settings">
|
||||
<i class="bi bi-gear me-2"></i>Ustawienia
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="p-3 border-top border-secondary">
|
||||
<small class="text-secondary">Zalogowano jako:</small><br>
|
||||
<span class="text-white"><?= htmlspecialchars(\App\Core\Auth::user()['username'] ?? '') ?></span>
|
||||
<a href="/change-password" class="d-block text-secondary small mt-1"><i class="bi bi-key me-1"></i>Zmień hasło</a>
|
||||
|
||||
<div class="flex-grow-1 py-4 overflow-y-auto">
|
||||
<div class="px-4 mb-3 text-uppercase text-secondary small fw-bold" style="font-size: 0.65rem; letter-spacing: 0.1em;">Menu główne</div>
|
||||
<ul class="nav flex-column mb-4">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?= \App\Core\Router::isCurrent('/') ? 'active' : '' ?>" href="/">
|
||||
<i class="bi bi-grid-1x2-fill"></i>Dashboard
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?= \App\Core\Router::isCurrent('/sites') ? 'active' : '' ?>" href="/sites">
|
||||
<i class="bi bi-browser-safari"></i>Strony WP
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?= \App\Core\Router::isCurrent('/seo/stats') ? 'active' : '' ?>" href="/seo/stats">
|
||||
<i class="bi bi-bar-chart-line-fill"></i>Statystyki SEO
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="px-4 mb-3 text-uppercase text-secondary small fw-bold" style="font-size: 0.65rem; letter-spacing: 0.1em;">Zasoby i Treści</div>
|
||||
<ul class="nav flex-column mb-4">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?= \App\Core\Router::isCurrent('/global-topics') ? 'active' : '' ?>" href="/global-topics">
|
||||
<i class="bi bi-tags-fill"></i>Biblioteka Tematów
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?= \App\Core\Router::isCurrent('/articles') ? 'active' : '' ?>" href="/articles">
|
||||
<i class="bi bi-journal-richtext"></i>Artykuły
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="px-4 mb-3 text-uppercase text-secondary small fw-bold" style="font-size: 0.65rem; letter-spacing: 0.1em;">Administracja</div>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?= \App\Core\Router::isCurrent('/installer') ? 'active' : '' ?>" href="/installer">
|
||||
<i class="bi bi-magic"></i>Instalator WP
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?= \App\Core\Router::isCurrent('/settings') ? 'active' : '' ?>" href="/settings">
|
||||
<i class="bi bi-sliders"></i>Ustawienia API
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?= \App\Core\Router::isCurrent('/logs') ? 'active' : '' ?>" href="/logs">
|
||||
<i class="bi bi-shield-lock-fill"></i>Dziennik Zdarzeń
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="p-4 bg-black bg-opacity-10 border-top border-white border-opacity-5">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="rounded-circle bg-secondary d-flex align-items-center justify-content-center text-white" style="width: 32px; height: 32px; font-size: 0.8rem; font-weight: 600;">
|
||||
<?= strtoupper(substr(\App\Core\Auth::user()['username'] ?? 'U', 0, 1)) ?>
|
||||
</div>
|
||||
<div class="overflow-hidden">
|
||||
<div class="text-white small text-truncate fw-medium"><?= htmlspecialchars(\App\Core\Auth::user()['username'] ?? 'Użytkownik') ?></div>
|
||||
<a href="/logout" class="text-secondary small text-decoration-none hover-white d-flex align-items-center">
|
||||
<i class="bi bi-box-arrow-right me-1"></i> Wyloguj
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
Reference in New Issue
Block a user