admin-panel

This commit is contained in:
2026-01-12 11:37:40 +00:00
parent e400b203b8
commit 2a83373b28
18 changed files with 507 additions and 2329 deletions

View File

@@ -0,0 +1,50 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AuthController extends Controller
{
/**
* Показать форму входа.
*/
public function showLoginForm()
{
return view('admin.login');
}
/**
* Обработать вход пользователя.
*/
public function login(Request $request)
{
$credentials = $request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
return redirect()->route('admin.hotels.index');
}
return back()->withErrors([
'email' => 'Неверные данные.',
])->onlyInput('email');
}
/**
* Выход пользователя.
*/
public function logout(Request $request)
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect()->route('admin.login.form');
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
//
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event to listener mappings for the application.
*
* @var array<class-string, array<int, class-string>>
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
//
}
/**
* Determine if events and listeners should be automatically discovered.
*
* @return bool
*/
public function shouldDiscoverEvents()
{
return false;
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace App\Providers;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* The path to your application's route files.
*
* @var string
*/
protected $routesPath;
/**
* Define your route model bindings, pattern filters, and other route configuration.
*
* @return void
*/
public function boot()
{
$this->configureRateLimiting();
// Установите путь к маршрутам
$this->routesPath = base_path('routes');
$this->routes(function () {
Route::middleware('web')
->group($this->routesPath . '/web.php');
Route::middleware(['web', 'auth'])
->prefix('admin')
->group($this->routesPath . '/admin.php');
});
}
/**
* Configure the rate limiters for the application.
*
* @return void
*/
protected function configureRateLimiting()
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
}
}

View File

@@ -2,5 +2,6 @@
return [
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\ResponseMacroServiceProvider::class,
];

View File

@@ -10,10 +10,12 @@
"barryvdh/laravel-dompdf": "^3.1",
"laravel/framework": "^12.0",
"laravel/sanctum": "^4.2",
"laravel/tinker": "^2.10.1"
"laravel/tinker": "^2.10.1",
"laravel/ui": "*"
},
"require-dev": {
"fakerphp/faker": "^1.23",
"laravel/breeze": "*",
"laravel/pail": "^1.2.2",
"laravel/pint": "^1.24",
"laravel/sail": "^1.41",

126
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "343ecaac4a8b061c5430a046847047e7",
"content-hash": "21efbfbbcf01cbe7cfa0cf7e625e9976",
"packages": [
{
"name": "barryvdh/laravel-dompdf",
@@ -1755,6 +1755,69 @@
},
"time": "2025-12-19T19:16:45+00:00"
},
{
"name": "laravel/ui",
"version": "v4.6.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/ui.git",
"reference": "7d6ffa38d79f19c9b3e70a751a9af845e8f41d88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/ui/zipball/7d6ffa38d79f19c9b3e70a751a9af845e8f41d88",
"reference": "7d6ffa38d79f19c9b3e70a751a9af845e8f41d88",
"shasum": ""
},
"require": {
"illuminate/console": "^9.21|^10.0|^11.0|^12.0",
"illuminate/filesystem": "^9.21|^10.0|^11.0|^12.0",
"illuminate/support": "^9.21|^10.0|^11.0|^12.0",
"illuminate/validation": "^9.21|^10.0|^11.0|^12.0",
"php": "^8.0",
"symfony/console": "^6.0|^7.0"
},
"require-dev": {
"orchestra/testbench": "^7.35|^8.15|^9.0|^10.0",
"phpunit/phpunit": "^9.3|^10.4|^11.5"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Ui\\UiServiceProvider"
]
},
"branch-alias": {
"dev-master": "4.x-dev"
}
},
"autoload": {
"psr-4": {
"Laravel\\Ui\\": "src/",
"Illuminate\\Foundation\\Auth\\": "auth-backend/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Laravel UI utilities and presets.",
"keywords": [
"laravel",
"ui"
],
"support": {
"source": "https://github.com/laravel/ui/tree/v4.6.1"
},
"time": "2025-01-28T15:15:29+00:00"
},
{
"name": "league/commonmark",
"version": "2.8.0",
@@ -6757,6 +6820,67 @@
},
"time": "2025-04-30T06:54:44+00:00"
},
{
"name": "laravel/breeze",
"version": "v2.3.8",
"source": {
"type": "git",
"url": "https://github.com/laravel/breeze.git",
"reference": "1a29c5792818bd4cddf70b5f743a227e02fbcfcd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/breeze/zipball/1a29c5792818bd4cddf70b5f743a227e02fbcfcd",
"reference": "1a29c5792818bd4cddf70b5f743a227e02fbcfcd",
"shasum": ""
},
"require": {
"illuminate/console": "^11.0|^12.0",
"illuminate/filesystem": "^11.0|^12.0",
"illuminate/support": "^11.0|^12.0",
"illuminate/validation": "^11.0|^12.0",
"php": "^8.2.0",
"symfony/console": "^7.0"
},
"require-dev": {
"laravel/framework": "^11.0|^12.0",
"orchestra/testbench-core": "^9.0|^10.0",
"phpstan/phpstan": "^2.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Breeze\\BreezeServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Laravel\\Breeze\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Minimal Laravel authentication scaffolding with Blade and Tailwind.",
"keywords": [
"auth",
"laravel"
],
"support": {
"issues": "https://github.com/laravel/breeze/issues",
"source": "https://github.com/laravel/breeze"
},
"time": "2025-07-18T18:49:59+00:00"
},
{
"name": "laravel/pail",
"version": "v1.2.4",

View File

@@ -1,15 +1,16 @@
<?php
return [
use Illuminate\Support\Facades\Facade;
return [
/*
|--------------------------------------------------------------------------
| Application Name
|--------------------------------------------------------------------------
|
| This value is the name of your application, which will be used when the
| This value is the name of your application. This value is used when the
| framework needs to place the application's name in a notification or
| other UI elements where an application name needs to be displayed.
| any other location as required by the application or its packages.
|
*/
@@ -27,9 +28,6 @@ return [
*/
'env' => env('APP_ENV', 'production'),
'providers' => [
App\Providers\ResponseMacroServiceProvider::class,
],
/*
|--------------------------------------------------------------------------
@@ -51,20 +49,22 @@ return [
|
| This URL is used by the console to properly generate URLs when using
| the Artisan command line tool. You should set this to the root of
| the application so that it's available within Artisan commands.
| your application so that it is used when running Artisan tasks.
|
*/
'url' => env('APP_URL', 'http://localhost'),
'asset_url' => env('ASSET_URL'),
/*
|--------------------------------------------------------------------------
| Application Timezone
|--------------------------------------------------------------------------
|
| Here you may specify the default timezone for your application, which
| will be used by the PHP date and date-time functions. The timezone
| is set to "UTC" by default as it is suitable for most use cases.
| will be used by the PHP date and date-time functions. We have gone
| ahead and set this to a sensible default for you out of the box.
|
*/
@@ -76,37 +76,53 @@ return [
|--------------------------------------------------------------------------
|
| The application locale determines the default locale that will be used
| by Laravel's translation / localization methods. This option can be
| set to any locale for which you plan to have translation strings.
| by the translation service provider. You are free to set this value
| to any of the locales which will be supported by the application.
|
*/
'locale' => env('APP_LOCALE', 'en'),
'locale' => 'en',
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
/*
|--------------------------------------------------------------------------
| Application Fallback Locale
|--------------------------------------------------------------------------
|
| The fallback locale determines the locale to use when the current one
| is not available. You may change the value to correspond to any of
| the language folders that are provided through your application.
|
*/
'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
'fallback_locale' => 'en',
/*
|--------------------------------------------------------------------------
| Faker Locale
|--------------------------------------------------------------------------
|
| This locale will be used by the Faker PHP library when generating fake
| data for your database seeds. For example, this will be used to get
| localized telephone numbers, street address information and more.
|
*/
'faker_locale' => 'en_US',
/*
|--------------------------------------------------------------------------
| Encryption Key
|--------------------------------------------------------------------------
|
| This key is utilized by Laravel's encryption services and should be set
| to a random, 32 character string to ensure that all encrypted values
| are secure. You should do this prior to deploying the application.
| This key is used by the Illuminate encrypter service and should be set
| to a random, 32 character string, otherwise these encrypted strings
| will not be safe. Please do this before deploying an application!
|
*/
'cipher' => 'AES-256-CBC',
'key' => env('APP_KEY'),
'previous_keys' => [
...array_filter(
explode(',', (string) env('APP_PREVIOUS_KEYS', ''))
),
],
'cipher' => 'AES-256-CBC',
/*
|--------------------------------------------------------------------------
@@ -122,8 +138,67 @@ return [
*/
'maintenance' => [
'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),
'store' => env('APP_MAINTENANCE_STORE', 'database'),
'driver' => 'file',
],
/*
|--------------------------------------------------------------------------
| Autoloaded Service Providers
|--------------------------------------------------------------------------
|
| The service providers listed here will be automatically loaded on the
| request to your application. Feel free to add your own services to
| this array to grant expanded functionality to your applications.
|
*/
'providers' => [
// Laravel Framework Service Providers...
Illuminate\Auth\AuthServiceProvider::class,
Illuminate\Broadcasting\BroadcastServiceProvider::class,
Illuminate\Bus\BusServiceProvider::class,
Illuminate\Cache\CacheServiceProvider::class,
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
Illuminate\Cookie\CookieServiceProvider::class,
Illuminate\Database\DatabaseServiceProvider::class,
Illuminate\Encryption\EncryptionServiceProvider::class,
Illuminate\Filesystem\FilesystemServiceProvider::class, // ← ОБЯЗАТЕЛЬНО!
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
Illuminate\Hashing\HashServiceProvider::class,
Illuminate\Mail\MailServiceProvider::class,
Illuminate\Notifications\NotificationServiceProvider::class,
Illuminate\Pagination\PaginationServiceProvider::class,
Illuminate\Pipeline\PipelineServiceProvider::class,
Illuminate\Queue\QueueServiceProvider::class,
Illuminate\Redis\RedisServiceProvider::class,
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
Illuminate\Session\SessionServiceProvider::class,
Illuminate\Translation\TranslationServiceProvider::class,
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
// Package Service Providers...
// Application Service Providers...
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
],
/*
|--------------------------------------------------------------------------
| Class Aliases
|--------------------------------------------------------------------------
|
| This array of class aliases will be registered when this application
| is started. However, feel free to register as many as you wish as
| the aliases are "lazy" loaded so they don't hinder performance.
|
*/
'aliases' => Facade::defaultAliases()->merge([
// 'Example' => App\Facades\Example::class,
])->toArray(),
];

View File

@@ -1,41 +1,12 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Filesystem Disk
|--------------------------------------------------------------------------
|
| Here you may specify the default filesystem disk that should be used
| by the framework. The "local" disk, as well as a variety of cloud
| based disks are available to your application for file storage.
|
*/
'default' => env('FILESYSTEM_DISK', 'local'),
/*
|--------------------------------------------------------------------------
| Filesystem Disks
|--------------------------------------------------------------------------
|
| Below you may configure as many filesystem disks as necessary, and you
| may even configure multiple disks for the same driver. Examples for
| most supported storage drivers are configured here for reference.
|
| Supported drivers: "local", "ftp", "sftp", "s3"
|
*/
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app/private'),
'serve' => true,
'throw' => false,
'report' => false,
'root' => storage_path('app'),
],
'public' => [
@@ -43,8 +14,6 @@ return [
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'throw' => false,
'report' => false,
],
's3' => [
@@ -56,25 +25,10 @@ return [
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
'throw' => false,
'report' => false,
],
],
/*
|--------------------------------------------------------------------------
| Symbolic Links
|--------------------------------------------------------------------------
|
| Here you may configure the symbolic links that will be created when the
| `storage:link` Artisan command is executed. The array keys should be
| the locations of the links and the values should be their targets.
|
*/
'links' => [
public_path('storage') => storage_path('app/public'),
],
];
];

View File

@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddDefaultPhoneToUsersTable extends Migration
{
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->default('')->change();
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->nullable()->change();
});
}
}

2226
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,11 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
"private": true,
"scripts": {
"build": "vite build",
"dev": "vite"
},
"devDependencies": {
"@tailwindcss/vite": "^4.0.0",
"axios": "^1.11.0",
"concurrently": "^9.0.1",
"laravel-vite-plugin": "^2.0.0",
"tailwindcss": "^4.0.0",
"vite": "^7.0.7"
}
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"laravel-vite-plugin": "^1.0",
"vite": "^5.0"
}
}

View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Вход в админку</title>
<style>
body { font-family: sans-serif; max-width: 400px; margin: 50px auto; }
input { width: 100%; padding: 8px; margin: 5px 0; }
button { width: 100%; padding: 10px; background: #42b983; color: white; border: none; cursor: pointer; }
.error { color: red; }
</style>
</head>
<body>
<h1>Вход в админку</h1>
@if ($errors->any())
<div class="error">
@foreach ($errors->all() as $error)
<p>{{ $error }}</p>
@endforeach
</div>
@endif
<form method="POST" action="{{ route('admin.login') }}">
@csrf
<input type="email" name="email" placeholder="Email" required value="{{ old('email') }}">
<input type="password" name="password" placeholder="Пароль" required>
<button type="submit">Войти</button>
</form>
</body>
</html>

18
routes/admin.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
use Illuminate\Support\Facades\Route;
Route::get('/login', [\App\Http\Controllers\Admin\AuthController::class, 'showLoginForm'])
->name('admin.login.form');
Route::post('/login', [\App\Http\Controllers\Admin\AuthController::class, 'login'])
->name('admin.login');
Route::middleware('auth')->group(function () {
Route::get('/hotels', function () {
return '<h1>Отели</h1><a href="/admin/logout">Выйти</a>';
})->name('admin.hotels.index');
Route::post('/logout', [\App\Http\Controllers\Admin\AuthController::class, 'logout'])
->name('admin.logout');
});

View File

@@ -14,6 +14,9 @@ Route::middleware('auth:sanctum')->group(function () {
Route::post('/bookings/{id}/invoice', [InvoiceController::class, 'generate']);
});
Route::get('/test', function () {
return response()->success(['message' => 'Тест прошёл успешно!']);
});
Route::post('/admin/login', [AdminAuthController::class, 'login']);
Route::post('/admin/logout', [AdminAuthController::class, 'logout'])->middleware('auth:sanctum');

View File

@@ -1,7 +1,25 @@
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Admin\AuthController;
// Гость → форма входа
Route::get('/admin/login', [AuthController::class, 'showLoginForm'])->name('admin.login.form');
Route::post('/admin/login', [AuthController::class, 'login'])->name('admin.login');
// Авторизованный → админка
Route::middleware('auth')->prefix('admin')->group(function () {
Route::get('/hotels', function () {
return '<h1>Отели</h1><a href="/admin/logout">Выйти</a>';
})->name('admin.hotels.index');
Route::post('/logout', [AuthController::class, 'logout'])->name('admin.logout');
});
Route::get('/', function () {
return view('welcome');
});
Route::get('/{any?}', function () {
return view('app');
})->where('any', '.*');

View File

@@ -1,13 +0,0 @@
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
tailwindcss(),
],
});