parent
1a138e86dc
commit
1f0c97794e
13 changed files with 265 additions and 66 deletions
@ -0,0 +1,40 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Http\Controllers\Auth; |
||||||
|
|
||||||
|
use App\Http\Controllers\Controller; |
||||||
|
use Illuminate\Http\Request; |
||||||
|
use Illuminate\Support\Facades\Auth; |
||||||
|
|
||||||
|
class LoginController extends Controller |
||||||
|
{ |
||||||
|
public function showLoginForm() |
||||||
|
{ |
||||||
|
return view('auth.login'); |
||||||
|
} |
||||||
|
|
||||||
|
public function login(Request $request) |
||||||
|
{ |
||||||
|
$data = $request->validate([ |
||||||
|
'email' => ['required','email'], |
||||||
|
'password' => ['required','string'], |
||||||
|
]); |
||||||
|
|
||||||
|
if (Auth::attempt($data, $request->boolean('remember'))) { |
||||||
|
$request->session()->regenerate(); |
||||||
|
return redirect()->intended(route('dashboard')); |
||||||
|
} |
||||||
|
|
||||||
|
return back() |
||||||
|
->withErrors(['email' => 'Email hoặc mật khẩu không đúng.']) |
||||||
|
->withInput(['email' => $request->email]); |
||||||
|
} |
||||||
|
|
||||||
|
public function logout(Request $request) |
||||||
|
{ |
||||||
|
Auth::logout(); |
||||||
|
$request->session()->invalidate(); |
||||||
|
$request->session()->regenerateToken(); |
||||||
|
return redirect()->route('login'); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace App\Livewire; |
||||||
|
|
||||||
|
use Livewire\Component; |
||||||
|
|
||||||
|
class Dashboard extends Component |
||||||
|
{ |
||||||
|
public function render() |
||||||
|
{ |
||||||
|
return view('livewire.dashboard')->layout('layouts.app', ['title' => 'Dashboard']); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
@extends('layouts.auth') |
||||||
|
|
||||||
|
@section('title','Đăng nhập hệ thống') |
||||||
|
|
||||||
|
@section('content') |
||||||
|
<div class="row"> |
||||||
|
<div class="col-lg-4 col-md-6 col-sm-8 mx-auto"> |
||||||
|
<div class="card card-body mt-4 shadow-lg"> |
||||||
|
<h4 class="text-center mb-4">Đăng nhập</h4> |
||||||
|
<form method="POST" action="{{ route('login') }}"> |
||||||
|
@csrf |
||||||
|
|
||||||
|
{{-- Email --}} |
||||||
|
<div class="mb-3"> |
||||||
|
<label for="email" class="form-label">Email</label> |
||||||
|
<input id="email" type="email" name="email" |
||||||
|
class="form-control @error('email') is-invalid @enderror" |
||||||
|
value="{{ old('email') }}" required autofocus> |
||||||
|
@error('email') |
||||||
|
<div class="invalid-feedback">{{ $message }}</div> |
||||||
|
@enderror |
||||||
|
</div> |
||||||
|
|
||||||
|
{{-- Password --}} |
||||||
|
<div class="mb-3"> |
||||||
|
<label for="password" class="form-label">Mật khẩu</label> |
||||||
|
<input id="password" type="password" name="password" |
||||||
|
class="form-control @error('password') is-invalid @enderror" |
||||||
|
required> |
||||||
|
@error('password') |
||||||
|
<div class="invalid-feedback">{{ $message }}</div> |
||||||
|
@enderror |
||||||
|
</div> |
||||||
|
|
||||||
|
{{-- Remember --}} |
||||||
|
<div class="form-check form-switch mb-3"> |
||||||
|
<input class="form-check-input" type="checkbox" name="remember" id="remember"> |
||||||
|
<label class="form-check-label" for="remember">Ghi nhớ đăng nhập</label> |
||||||
|
</div> |
||||||
|
|
||||||
|
{{-- Submit --}} |
||||||
|
<div class="d-grid"> |
||||||
|
<button type="submit" class="btn btn-primary"> |
||||||
|
Đăng nhập |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
|
||||||
|
{{-- Forgot Password --}} |
||||||
|
@if(Route::has('password.request')) |
||||||
|
<p class="text-center text-sm mt-3"> |
||||||
|
<a href="{{ route('password.request') }}">Quên mật khẩu?</a> |
||||||
|
</p> |
||||||
|
@endif |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
@endsection |
@ -1,21 +1,51 @@ |
|||||||
|
{{-- resources/views/layouts/soft-ui.blade.php --}} |
||||||
<!DOCTYPE html> |
<!DOCTYPE html> |
||||||
<html lang="vi"> |
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> |
||||||
|
|
||||||
<head> |
<head> |
||||||
<meta charset="UTF-8"> |
<meta charset="utf-8" /> |
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
<meta name="viewport" content="width=device-width, initial-scale=1" /> |
||||||
<title>Đăng nhập hệ thống</title> |
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet" /> |
<title>@yield('title', 'Dashboard')</title> |
||||||
@vite('resources/css/app.css') |
|
||||||
|
{{-- 1. Soft UI CSS --}} |
||||||
|
<link rel="stylesheet" href="{{ asset('soft-ui/assets/css/soft-ui-dashboard.css') }}" /> |
||||||
|
|
||||||
|
{{-- 2. Google fonts / Icons (nếu cần) --}} |
||||||
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet" /> |
||||||
|
|
||||||
|
{{-- 3. Livewire --}} |
||||||
@livewireStyles |
@livewireStyles |
||||||
|
|
||||||
|
{{-- 4. CSS bổ sung --}} |
||||||
|
@stack('css') |
||||||
</head> |
</head> |
||||||
|
|
||||||
<body class="font-sans antialiased bg-cover bg-center" style="background-image: url('{{ asset('images/logo.png') }}')"> |
<body class="g-sidenav-show bg-gray-100"> |
||||||
<div class="min-h-screen flex items-center justify-center bg-gray-900 bg-opacity-50"> |
{{-- Ảnh nền header (tùy chọn) --}} |
||||||
{{ $slot }} |
<div class="min-height-300 bg-primary position-absolute w-100"></div> |
||||||
</div> |
|
||||||
|
|
||||||
|
{{-- Sidebar --}} |
||||||
|
@include('layouts.partials.sidebar') |
||||||
|
|
||||||
|
<main class="main-content position-relative max-height-vh-100 h-100 border-radius-lg"> |
||||||
|
{{-- Navbar --}} |
||||||
|
@include('layouts.partials.navbar') |
||||||
|
|
||||||
|
{{-- Nội dung chính --}} |
||||||
|
<div class="container-fluid py-4"> |
||||||
|
@yield('content') |
||||||
|
</div> |
||||||
|
</main> |
||||||
|
|
||||||
|
{{-- 5. Core JS bundle (đã gồm Popper & Bootstrap) --}} |
||||||
|
<script src="{{ asset('soft-ui/assets/js/soft-ui-dashboard.min.js') }}"></script> |
||||||
|
|
||||||
|
{{-- 6. Livewire --}} |
||||||
@livewireScripts |
@livewireScripts |
||||||
|
|
||||||
|
{{-- 7. JS bổ sung --}} |
||||||
|
@stack('js') |
||||||
</body> |
</body> |
||||||
|
|
||||||
</html> |
</html> |
||||||
|
@ -0,0 +1,38 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="vi"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"/> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> |
||||||
|
|
||||||
|
<title>@yield('title','Auth')</title> |
||||||
|
|
||||||
|
{{-- Soft UI CSS --}} |
||||||
|
<link rel="stylesheet" href="{{ asset('soft-ui/assets/css/soft-ui-dashboard.css') }}"/> |
||||||
|
|
||||||
|
{{-- Livewire Styles --}} |
||||||
|
@livewireStyles |
||||||
|
|
||||||
|
{{-- CSS bổ sung --}} |
||||||
|
@stack('css') |
||||||
|
</head> |
||||||
|
<body class="bg-gray-100"> |
||||||
|
<section class="min-vh-100 d-flex align-items-center justify-content-center"> |
||||||
|
<div class="container"> |
||||||
|
@yield('content') |
||||||
|
</div> |
||||||
|
</section> |
||||||
|
|
||||||
|
{{-- Core JS --}} |
||||||
|
<script src="{{ asset('soft-ui/assets/js/core/popper.min.js') }}"></script> |
||||||
|
<script src="{{ asset('soft-ui/assets/js/core/bootstrap.min.js') }}"></script> |
||||||
|
<script src="{{ asset('soft-ui/assets/js/plugins/perfect-scrollbar.min.js') }}"></script> |
||||||
|
<script src="{{ asset('soft-ui/assets/js/plugins/smooth-scrollbar.min.js') }}"></script> |
||||||
|
<script src="{{ asset('soft-ui/assets/js/soft-ui-dashboard.min.js') }}"></script> |
||||||
|
|
||||||
|
{{-- Livewire Scripts --}} |
||||||
|
@livewireScripts |
||||||
|
|
||||||
|
{{-- JS bổ sung --}} |
||||||
|
@stack('js') |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,22 @@ |
|||||||
|
{{-- resources/views/layouts/partials/navbar-soft-ui.blade.php --}} |
||||||
|
<nav class="navbar navbar-main navbar-expand-lg px-0 mx-4 shadow-none border-radius-xl"> |
||||||
|
<div class="container-fluid py-1 px-3"> |
||||||
|
<nav aria-label="breadcrumb"> |
||||||
|
<ol class="breadcrumb bg-transparent mb-0 pb-0 pt-1 px-0 me-sm-6 me-5"> |
||||||
|
<li class="breadcrumb-item text-sm"><a class="opacity-5 text-dark" href="#">Pages</a></li> |
||||||
|
<li class="breadcrumb-item text-sm text-dark active" aria-current="page">@yield('title')</li> |
||||||
|
</ol> |
||||||
|
<h6 class="font-weight-bolder mb-0">@yield('title')</h6> |
||||||
|
</nav> |
||||||
|
<ul class="navbar-nav justify-content-end ms-auto"> |
||||||
|
<li class="nav-item d-flex align-items-center"> |
||||||
|
<form method="POST" action="{{ route('logout') }}"> |
||||||
|
@csrf |
||||||
|
<button type="submit" class="btn btn-link text-dark"> |
||||||
|
<i class="material-icons-round">logout</i> Đăng xuất |
||||||
|
</button> |
||||||
|
</form> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</nav> |
@ -0,0 +1,20 @@ |
|||||||
|
{{-- resources/views/layouts/partials/sidebar-soft-ui.blade.php --}} |
||||||
|
<aside class="sidenav navbar navbar-vertical navbar-expand-xs border-0 border-radius-xl my-3 fixed-start ms-3"> |
||||||
|
<div class="sidenav-header"> |
||||||
|
<a class="navbar-brand" href="{{ route('dashboard') }}"> |
||||||
|
<img src="{{ asset('images/logo.png') }}" class="navbar-brand-img" alt="logo"> |
||||||
|
<span class="ms-1 font-weight-bold">My App</span> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
<hr class="horizontal dark mt-0 mb-2"> |
||||||
|
<ul class="navbar-nav"> |
||||||
|
<li class="nav-item"> |
||||||
|
<a class="nav-link {{ request()->routeIs('dashboard') ? 'active' : '' }}" |
||||||
|
href="{{ route('dashboard') }}"> |
||||||
|
<i class="material-icons-round">dashboard</i> |
||||||
|
<span class="nav-link-text ms-2">Dashboard</span> |
||||||
|
</a> |
||||||
|
</li> |
||||||
|
{{-- các mục khác… --}} |
||||||
|
</ul> |
||||||
|
</aside> |
@ -1,45 +0,0 @@ |
|||||||
<div class="max-w-md w-full bg-white shadow-xl rounded-lg p-8 relative z-10"> |
|
||||||
<div class="flex justify-center mb-4"> |
|
||||||
<img src="{{ asset('images/logo.png') }}" alt="Logo" class="h-16 w-auto"> |
|
||||||
</div> |
|
||||||
|
|
||||||
<h2 class="text-2xl font-semibold text-center text-gray-900 mb-6">Đăng nhập hệ thống</h2> |
|
||||||
|
|
||||||
<form wire:submit.prevent="login" class="space-y-4"> |
|
||||||
<!-- Email --> |
|
||||||
<div> |
|
||||||
<label class="block text-sm font-medium text-gray-700">Email:</label> |
|
||||||
<input type="email" wire:model="email" required |
|
||||||
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm py-2 px-3 |
|
||||||
focus:ring-indigo-500 focus:border-indigo-500"> |
|
||||||
@error('email') |
|
||||||
<div class="text-red-500 text-sm">{{ $message }}</div> |
|
||||||
@enderror |
|
||||||
</div> |
|
||||||
|
|
||||||
<!-- Password --> |
|
||||||
<div> |
|
||||||
<label class="block text-sm font-medium text-gray-700">Mật khẩu:</label> |
|
||||||
<input type="password" wire:model="password" required |
|
||||||
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm py-2 px-3 |
|
||||||
focus:ring-indigo-500 focus:border-indigo-500"> |
|
||||||
@error('password') |
|
||||||
<div class="text-red-500 text-sm">{{ $message }}</div> |
|
||||||
@enderror |
|
||||||
</div> |
|
||||||
|
|
||||||
<!-- Remember --> |
|
||||||
<div class="flex items-center"> |
|
||||||
<input type="checkbox" wire:model="remember" id="remember" |
|
||||||
class="h-4 w-4 bg-red-500 border-gray-300 rounded"> |
|
||||||
<label for="remember" class="ml-2 text-sm text-gray-900">Ghi nhớ đăng nhập</label> |
|
||||||
</div> |
|
||||||
|
|
||||||
<!-- Button --> |
|
||||||
<button type="submit" |
|
||||||
class="block w-full py-3 bg-indigo-600 text-white font-medium rounded hover:bg-indigo-700 |
|
||||||
transition duration-200"> |
|
||||||
Đăng nhập |
|
||||||
</button> |
|
||||||
</form> |
|
||||||
</div> |
|
@ -0,0 +1,5 @@ |
|||||||
|
<div class="row"> |
||||||
|
<div class="col-12"> |
||||||
|
<h3>Xin chào, {{ auth()->user()->name }}!</h3> |
||||||
|
</div> |
||||||
|
</div> |
@ -1,9 +1,19 @@ |
|||||||
<?php |
<?php |
||||||
|
|
||||||
|
use App\Http\Controllers\Auth\LoginController; |
||||||
use Illuminate\Support\Facades\Route; |
use Illuminate\Support\Facades\Route; |
||||||
use App\Livewire\Auth\Login; |
use App\Livewire\Dashboard; |
||||||
|
|
||||||
Route::get('/', function () { |
// Form đăng nhập, chỉ cho guest |
||||||
return view('welcome'); |
Route::get('login', [LoginController::class, 'showLoginForm']) |
||||||
}); |
->middleware('guest') |
||||||
Route::get('/login', Login::class)->name('login')->middleware('guest'); |
->name('login'); |
||||||
|
Route::post('login', [LoginController::class, 'login']) |
||||||
|
->middleware('guest'); |
||||||
|
Route::post('logout', [LoginController::class, 'logout']) |
||||||
|
->middleware('auth') |
||||||
|
->name('logout'); |
||||||
|
|
||||||
|
Route::get('dashboard', Dashboard::class) |
||||||
|
->name('dashboard') |
||||||
|
->middleware(['auth']); |
||||||
|
@ -1,13 +1,18 @@ |
|||||||
import { defineConfig } from 'vite'; |
import { defineConfig } from "vite"; |
||||||
import laravel from 'laravel-vite-plugin'; |
import laravel from "laravel-vite-plugin"; |
||||||
import tailwindcss from '@tailwindcss/vite'; |
import tailwindcss from "@tailwindcss/vite"; |
||||||
|
|
||||||
export default defineConfig({ |
export default defineConfig({ |
||||||
plugins: [ |
plugins: [ |
||||||
laravel({ |
laravel({ |
||||||
input: ['resources/css/app.css', 'resources/js/app.js'], |
input: ["resources/css/app.css", "resources/js/app.js"], |
||||||
refresh: true, |
refresh: true, |
||||||
}), |
}), |
||||||
tailwindcss(), |
tailwindcss(), |
||||||
], |
], |
||||||
|
server: { |
||||||
|
fs: { |
||||||
|
allow: [".", "public/soft-ui/assets"], |
||||||
|
}, |
||||||
|
}, |
||||||
}); |
}); |
||||||
|
Loading…
Reference in new issue