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> |
||||
<html lang="vi"> |
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> |
||||
|
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
<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" /> |
||||
@vite('resources/css/app.css') |
||||
<meta charset="utf-8" /> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1" /> |
||||
|
||||
<title>@yield('title', 'Dashboard')</title> |
||||
|
||||
{{-- 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 |
||||
|
||||
{{-- 4. CSS bổ sung --}} |
||||
@stack('css') |
||||
</head> |
||||
|
||||
<body class="font-sans antialiased bg-cover bg-center" style="background-image: url('{{ asset('images/logo.png') }}')"> |
||||
<div class="min-h-screen flex items-center justify-center bg-gray-900 bg-opacity-50"> |
||||
{{ $slot }} |
||||
<body class="g-sidenav-show bg-gray-100"> |
||||
{{-- Ảnh nền header (tùy chọn) --}} |
||||
<div class="min-height-300 bg-primary position-absolute w-100"></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 |
||||
|
||||
{{-- 7. JS bổ sung --}} |
||||
@stack('js') |
||||
</body> |
||||
|
||||
</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 |
||||
|
||||
use App\Http\Controllers\Auth\LoginController; |
||||
use Illuminate\Support\Facades\Route; |
||||
use App\Livewire\Auth\Login; |
||||
use App\Livewire\Dashboard; |
||||
|
||||
Route::get('/', function () { |
||||
return view('welcome'); |
||||
}); |
||||
Route::get('/login', Login::class)->name('login')->middleware('guest'); |
||||
// Form đăng nhập, chỉ cho guest |
||||
Route::get('login', [LoginController::class, 'showLoginForm']) |
||||
->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 laravel from 'laravel-vite-plugin'; |
||||
import tailwindcss from '@tailwindcss/vite'; |
||||
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'], |
||||
input: ["resources/css/app.css", "resources/js/app.js"], |
||||
refresh: true, |
||||
}), |
||||
tailwindcss(), |
||||
], |
||||
server: { |
||||
fs: { |
||||
allow: [".", "public/soft-ui/assets"], |
||||
}, |
||||
}, |
||||
}); |
||||
|
Loading…
Reference in new issue