feature: login and my page
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Services\Admin\Contracts\AdminServiceInterface;
|
use App\Services\Admin\Contracts\AdminServiceInterface;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers\User;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Administration;
|
use App\Models\Administration;
|
||||||
use App\Services\User\Contracts\UserServiceInterface;
|
use App\Services\User\Contracts\UserServiceInterface;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware\Admin;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware\User;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -12,7 +12,7 @@ class MemberMiddleware
|
|||||||
{
|
{
|
||||||
public function handle(Request $request, Closure $next): Response
|
public function handle(Request $request, Closure $next): Response
|
||||||
{
|
{
|
||||||
if (Auth::check() && Auth::user()->role == User::ROLE_MEMBER && Auth::user()->status == User::STATUS_ACTIVE) {
|
if (Auth::check() && in_array(Auth::user()->role, [User::ROLE_MEMBER, User::ROLE_ADMIN]) && Auth::user()->status == User::STATUS_ACTIVE) {
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
return redirect()->route('login');
|
return redirect()->route('login');
|
||||||
@@ -40,10 +40,6 @@ class AuthService implements AuthServiceInterface
|
|||||||
return route('user.change_password');
|
return route('user.change_password');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($user->role == User::ROLE_ADMIN) {
|
|
||||||
return route('admin.dashboard');
|
|
||||||
}
|
|
||||||
|
|
||||||
return route('user.dashboard');
|
return route('user.dashboard');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,19 +3,24 @@
|
|||||||
use Illuminate\Foundation\Application;
|
use Illuminate\Foundation\Application;
|
||||||
use Illuminate\Foundation\Configuration\Exceptions;
|
use Illuminate\Foundation\Configuration\Exceptions;
|
||||||
use Illuminate\Foundation\Configuration\Middleware;
|
use Illuminate\Foundation\Configuration\Middleware;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
return Application::configure(basePath: dirname(__DIR__))
|
return Application::configure(basePath: dirname(__DIR__))
|
||||||
->withRouting(
|
->withRouting(
|
||||||
web: __DIR__.'/../routes/web.php',
|
web: __DIR__.'/../routes/web.php',
|
||||||
commands: __DIR__.'/../routes/console.php',
|
commands: __DIR__.'/../routes/console.php',
|
||||||
health: '/up',
|
health: '/up',
|
||||||
|
then: function () {
|
||||||
|
Route::middleware('web')
|
||||||
|
->group(base_path('routes/admin.php'));
|
||||||
|
},
|
||||||
)
|
)
|
||||||
->withMiddleware(function (Middleware $middleware): void {
|
->withMiddleware(function (Middleware $middleware): void {
|
||||||
$middleware->trustProxies(at: '*');
|
$middleware->trustProxies(at: '*');
|
||||||
|
|
||||||
$middleware->alias([
|
$middleware->alias([
|
||||||
'admin' => \App\Http\Middleware\AdminMiddleware::class,
|
'admin' => \App\Http\Middleware\Admin\AdminMiddleware::class,
|
||||||
'member' => \App\Http\Middleware\MemberMiddleware::class,
|
'member' => \App\Http\Middleware\User\MemberMiddleware::class,
|
||||||
'force_change_password' => \App\Http\Middleware\ForceChangePasswordMiddleware::class,
|
'force_change_password' => \App\Http\Middleware\ForceChangePasswordMiddleware::class,
|
||||||
]);
|
]);
|
||||||
})
|
})
|
||||||
|
|||||||
|
After Width: | Height: | Size: 390 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 333 KiB |
|
After Width: | Height: | Size: 553 KiB |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-full h-full">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 531 B |
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-full h-full">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 485 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-full h-full">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0V10.5m-2.812 10.5h14.625c.621 0 1.125-.504 1.125-1.125V11.25c0-.621-.504-1.125-1.125-1.125H3.75c-.621 0-1.125.504-1.125 1.125v7.875c0 .621.504 1.125 1.125 1.125z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 399 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-full h-full">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 452 B |
@@ -1,3 +1,5 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Caveat:wght@700&display=swap');
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'SVN-Poppins-Regular';
|
font-family: 'SVN-Poppins-Regular';
|
||||||
src: url('/fonts/FZ Poppins-Regular.ttf') format('truetype');
|
src: url('/fonts/FZ Poppins-Regular.ttf') format('truetype');
|
||||||
@@ -85,6 +87,10 @@
|
|||||||
|
|
||||||
--color-calendar-header: #4b729f;
|
--color-calendar-header: #4b729f;
|
||||||
|
|
||||||
|
--color-terminal-bg: #263238;
|
||||||
|
--color-terminal-base: #b0bec5;
|
||||||
|
--color-terminal-accent: #90a4ae;
|
||||||
|
|
||||||
--shadow-card: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
|
--shadow-card: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
|
||||||
--shadow-sidebar: 0 4px 20px 0 rgba(0, 0, 0, 0.05);
|
--shadow-sidebar: 0 4px 20px 0 rgba(0, 0, 0, 0.05);
|
||||||
--shadow-header: 0 2px 4px 0 rgba(0, 0, 0, 0.02);
|
--shadow-header: 0 2px 4px 0 rgba(0, 0, 0, 0.02);
|
||||||
@@ -261,3 +267,6 @@ select.form-input {
|
|||||||
.table-action-link {
|
.table-action-link {
|
||||||
@apply hover:text-primary-hover font-semibold underline underline-offset-2;
|
@apply hover:text-primary-hover font-semibold underline underline-offset-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@import "./login.css";
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/* resources/css/login.css */
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fade-in {
|
||||||
|
animation: fadeIn 0.3s ease-in-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-group {
|
||||||
|
@apply relative w-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-input {
|
||||||
|
@apply w-full h-[56px] pl-11 pr-12 text-sm text-text-dark bg-transparent border border-[#c4c4c4] rounded outline-none transition-all duration-200 ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-input:hover {
|
||||||
|
@apply border-text-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-input:focus {
|
||||||
|
@apply border-2 border-primary pl-[43px];
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-label {
|
||||||
|
@apply absolute left-11 top-1/2 -translate-y-1/2 text-sm text-text-muted pointer-events-none transition-all duration-200 ease-in-out bg-transparent p-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-input:focus ~ .floating-label,
|
||||||
|
.floating-input:not(:placeholder-shown) ~ .floating-label {
|
||||||
|
@apply top-0 -translate-y-1/2 text-xs text-primary bg-white px-1.5 left-10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-input:not(:focus):not(:placeholder-shown) ~ .floating-label {
|
||||||
|
@apply text-text-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-icon {
|
||||||
|
@apply absolute left-4 top-1/2 -translate-y-1/2 text-text-muted pointer-events-none transition-colors duration-200 ease-in-out flex items-center justify-center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-input:focus ~ .floating-icon {
|
||||||
|
@apply text-primary;
|
||||||
|
}
|
||||||
@@ -25,3 +25,51 @@ window.openDeleteModal = function(msnv, url) {
|
|||||||
window.openModal('deleteModal');
|
window.openModal('deleteModal');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.togglePasswordVisibility = function(inputId, button) {
|
||||||
|
const input = document.getElementById(inputId);
|
||||||
|
if (!input) return;
|
||||||
|
|
||||||
|
const eyeOpen = button.querySelector('.eye-icon-open');
|
||||||
|
const eyeClosed = button.querySelector('.eye-icon-closed');
|
||||||
|
|
||||||
|
if (input.type === 'password') {
|
||||||
|
input.type = 'text';
|
||||||
|
button.setAttribute('aria-label', 'Hide password');
|
||||||
|
if (eyeOpen) eyeOpen.classList.remove('hidden');
|
||||||
|
if (eyeClosed) eyeClosed.classList.add('hidden');
|
||||||
|
} else {
|
||||||
|
input.type = 'password';
|
||||||
|
button.setAttribute('aria-label', 'Show password');
|
||||||
|
if (eyeOpen) eyeOpen.classList.add('hidden');
|
||||||
|
if (eyeClosed) eyeClosed.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const loginForm = document.querySelector('form[action$="/login"]');
|
||||||
|
if (loginForm) {
|
||||||
|
loginForm.addEventListener('submit', (e) => {
|
||||||
|
const submitBtn = loginForm.querySelector('button[type="submit"]');
|
||||||
|
if (submitBtn) {
|
||||||
|
if (submitBtn.disabled) {
|
||||||
|
e.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
|
||||||
|
const originalText = submitBtn.textContent.trim();
|
||||||
|
submitBtn.dataset.originalText = originalText;
|
||||||
|
|
||||||
|
submitBtn.innerHTML = `
|
||||||
|
<svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||||
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||||
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||||
|
</svg>
|
||||||
|
<span>${originalText}</span>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('title', 'Tính năng đang phát triển')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="h-[calc(100vh-120px)] w-full flex items-center justify-center bg-white rounded-3xl border border-gray-100 shadow-sm">
|
||||||
|
<x-coming-soon />
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<div class="flex flex-col items-center justify-center h-full w-full text-center px-6 py-12 md:py-20">
|
||||||
|
<!-- Illustration Wrapper -->
|
||||||
|
<div class="relative w-full max-w-[280px] md:max-w-[340px] aspect-square mb-10 mx-auto flex items-center justify-center">
|
||||||
|
<!-- Floating decorative elements -->
|
||||||
|
<div class="absolute top-10 left-4 animate-[bounce_3s_infinite]">
|
||||||
|
<x-icon-star class="w-8 h-8 text-yellow-400 opacity-80" />
|
||||||
|
</div>
|
||||||
|
<div class="absolute bottom-20 left-10 animate-[pulse_4s_infinite]">
|
||||||
|
<x-icon-sparkle class="w-6 h-6 text-pink-400 opacity-60" />
|
||||||
|
</div>
|
||||||
|
<div class="absolute top-20 right-10 animate-[bounce_4s_infinite_reverse]">
|
||||||
|
<x-icon-star class="w-10 h-10 text-blue-400 opacity-70" />
|
||||||
|
</div>
|
||||||
|
<div class="absolute bottom-16 right-4 animate-[pulse_3s_infinite]">
|
||||||
|
<x-icon-sparkle class="w-8 h-8 text-purple-400 opacity-80" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Background blob glows -->
|
||||||
|
<div class="absolute inset-0 flex items-center justify-center pointer-events-none">
|
||||||
|
<div class="w-48 h-48 bg-blue-100/60 rounded-full blur-3xl absolute animate-blob"></div>
|
||||||
|
<div class="w-40 h-40 bg-pink-100/50 rounded-full blur-3xl absolute translate-x-12 animate-blob animation-delay-2000"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Custom Rocket SVG -->
|
||||||
|
<div class="relative z-10 animate-float">
|
||||||
|
<x-icon-rocket class="w-64 h-64 md:w-72 md:h-72 drop-shadow-2xl" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<h1 class="text-[28px] md:text-[34px] font-extrabold text-[#1a2b49] mb-4 tracking-tight">
|
||||||
|
Tính năng đang phát triển
|
||||||
|
</h1>
|
||||||
|
<p class="text-gray-500 font-medium max-w-[420px] mx-auto mb-10 leading-relaxed text-[15px]">
|
||||||
|
Chúng tôi đang nỗ lực để mang đến trải nghiệm tốt nhất cho bạn. Vui lòng quay lại sau nhé!
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Primary Button -->
|
||||||
|
<a href="{{ route('user.dashboard') }}" class="inline-flex items-center justify-center gap-2.5 px-8 py-3.5 bg-[#3462f7] hover:bg-blue-700 text-white font-bold rounded-xl shadow-[0_8px_16px_-4px_rgba(52,98,247,0.4)] transition-all hover:-translate-y-1 active:translate-y-0 text-[15px]">
|
||||||
|
<x-icon-arrow-left class="w-5 h-5 stroke-2" />
|
||||||
|
Quay về trang chủ
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@keyframes float {
|
||||||
|
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
||||||
|
50% { transform: translateY(-15px) rotate(2deg); }
|
||||||
|
}
|
||||||
|
.animate-float {
|
||||||
|
animation: float 5s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
@props([
|
||||||
|
'type' => 'text',
|
||||||
|
'name',
|
||||||
|
'id' => null,
|
||||||
|
'label' => '',
|
||||||
|
'required' => false,
|
||||||
|
'value' => '',
|
||||||
|
'autocomplete' => null,
|
||||||
|
'icon' => null,
|
||||||
|
'hasError' => false,
|
||||||
|
])
|
||||||
|
|
||||||
|
@php
|
||||||
|
$id = $id ?? $name;
|
||||||
|
$isPassword = $type === 'password';
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<div class="floating-group">
|
||||||
|
<input
|
||||||
|
type="{{ $type }}"
|
||||||
|
name="{{ $name }}"
|
||||||
|
id="{{ $id }}"
|
||||||
|
placeholder=" "
|
||||||
|
@if($required) required @endif
|
||||||
|
value="{{ $value }}"
|
||||||
|
@if($autocomplete) autocomplete="{{ $autocomplete }}" @endif
|
||||||
|
{{ $attributes->merge(['class' => 'floating-input' . ($hasError ? ' border-red-500 focus:border-red-500 focus:ring-red-500/20' : '')]) }}
|
||||||
|
@if($hasError)
|
||||||
|
aria-invalid="true"
|
||||||
|
aria-describedby="login-errors"
|
||||||
|
@endif
|
||||||
|
/>
|
||||||
|
<label for="{{ $id }}" class="floating-label{{ $hasError ? ' text-red-500' : '' }}">
|
||||||
|
{{ $label }}
|
||||||
|
@if($required)
|
||||||
|
<span class="text-red-500" aria-hidden="true">*</span>
|
||||||
|
@endif
|
||||||
|
</label>
|
||||||
|
@if($icon)
|
||||||
|
<span class="floating-icon{{ $hasError ? ' text-red-500' : '' }}">
|
||||||
|
<x-icon :name="$icon" class="w-5 h-5" />
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if($isPassword)
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="absolute right-3 top-1/2 -translate-y-1/2 text-text-muted hover:text-text-medium focus:text-primary focus:outline-none focus:ring-2 focus:ring-primary/20 rounded p-1 transition-colors duration-200 cursor-pointer"
|
||||||
|
onclick="togglePasswordVisibility('{{ $id }}', this)"
|
||||||
|
aria-label="Show password"
|
||||||
|
>
|
||||||
|
<x-icon name="eye" class="w-5 h-5 eye-icon-open" />
|
||||||
|
<x-icon name="eye-slash" class="w-5 h-5 eye-icon-closed hidden" />
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<header class="bg-transparent sticky top-0 z-30 pt-6 pb-2 px-8 flex justify-between items-center w-full">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<!-- Menu hamburger -->
|
||||||
|
<button id="sidebar-hamburger" class="p-2 text-gray-500 hover:text-gray-800 rounded-md focus:outline-none transition-colors">
|
||||||
|
<svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
|
||||||
|
<!-- Primary Action Button -->
|
||||||
|
<a href="{{ route('user.send') }}" class="hidden sm:flex items-center gap-2 px-5 py-2.5 bg-[#3462f7] hover:bg-blue-700 text-white text-[14px] font-bold rounded-xl shadow-md transition-all shadow-blue-500/20">
|
||||||
|
<span class="text-lg leading-none">+</span>
|
||||||
|
Gửi Thanks card
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<div class="bg-gradient-to-r from-[#eff4ff] to-[#faeffa] rounded-[24px] p-10 flex flex-col md:flex-row items-center justify-between w-full h-full border border-white shadow-sm overflow-hidden relative">
|
||||||
|
|
||||||
|
<!-- Content Left -->
|
||||||
|
<div class="flex-1 relative z-10 w-full md:pr-4">
|
||||||
|
<h2 class="text-[42px] font-extrabold text-[#1a2b49] flex items-center gap-3 mb-3 leading-none tracking-tight">
|
||||||
|
Thanks <span class="text-[#8b98e8] font-medium tracking-wider" style="font-family: 'Caveat', cursive, sans-serif; font-size: 52px; transform: translateY(-4px);">Card</span>
|
||||||
|
<svg class="w-8 h-8 text-[#8b98e8]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
|
||||||
|
</svg>
|
||||||
|
</h2>
|
||||||
|
<p class="text-[16px] text-gray-600 font-medium mb-8 leading-relaxed max-w-[320px]">
|
||||||
|
Một lời cảm ơn chân thành<br>có thể tạo nên ngày tuyệt vời của ai đó!
|
||||||
|
</p>
|
||||||
|
<a href="{{ route('user.send') }}" class="inline-flex items-center gap-2 px-8 py-3.5 bg-[#3462f7] hover:bg-blue-700 text-white font-semibold rounded-xl shadow-lg shadow-blue-500/25 transition-all text-[15px]">
|
||||||
|
Gửi lời cảm ơn ngay
|
||||||
|
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Illustration Right -->
|
||||||
|
<div class="w-[340px] shrink-0 relative flex justify-end">
|
||||||
|
<img src="{{ asset('images/hero_banner_illustration.png') }}" alt="Illustration" class="w-full max-w-[320px] object-contain drop-shadow-xl z-10 mix-blend-multiply">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Background Elements -->
|
||||||
|
<div class="absolute inset-0 z-0 opacity-50 pointer-events-none overflow-hidden">
|
||||||
|
<div class="absolute top-10 left-1/3 w-2 h-2 bg-pink-400 rounded-full blur-[1px]"></div>
|
||||||
|
<div class="absolute bottom-12 left-[40%] w-3 h-3 bg-blue-400 rounded-full blur-[1px]"></div>
|
||||||
|
<div class="absolute top-1/4 right-[45%] w-3 h-3 bg-yellow-400 rounded-full blur-[1px]"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg" {{ $attributes }}>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 212 B |
@@ -0,0 +1,27 @@
|
|||||||
|
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" {{ $attributes }}>
|
||||||
|
<g transform="rotate(45, 100, 100)">
|
||||||
|
<!-- Main Body Base -->
|
||||||
|
<path d="M100 20 C150 70, 160 130, 140 160 L60 160 C40 130, 50 70, 100 20 Z" fill="#E2E8F0" />
|
||||||
|
<path d="M100 20 C130 70, 120 130, 100 160 C80 130, 70 70, 100 20 Z" fill="#F8FAFC" />
|
||||||
|
|
||||||
|
<!-- Nose Cone -->
|
||||||
|
<path d="M100 20 C120 40, 125 55, 125 70 L75 70 C75 55, 80 40, 100 20 Z" fill="#3462F7" />
|
||||||
|
|
||||||
|
<!-- Windows -->
|
||||||
|
<circle cx="100" cy="95" r="22" fill="#94A3B8" />
|
||||||
|
<circle cx="100" cy="95" r="16" fill="#1E293B" />
|
||||||
|
<circle cx="104" cy="91" r="6" fill="#60A5FA" opacity="0.8" />
|
||||||
|
|
||||||
|
<!-- Fins -->
|
||||||
|
<path d="M60 130 L10 180 L60 150 Z" fill="#2563EB" />
|
||||||
|
<path d="M140 130 L190 180 L140 150 Z" fill="#2563EB" />
|
||||||
|
<path d="M100 130 L95 180 L105 180 Z" fill="#1E3A8A" />
|
||||||
|
|
||||||
|
<!-- Exhaust base -->
|
||||||
|
<path d="M80 160 L120 160 L110 175 L90 175 Z" fill="#475569" />
|
||||||
|
|
||||||
|
<!-- Flames -->
|
||||||
|
<path d="M90 175 C 90 200, 100 230, 100 230 C 100 230, 110 200, 110 175 Z" fill="#F59E0B" />
|
||||||
|
<path d="M95 175 C 95 190, 100 210, 100 210 C 100 210, 105 190, 105 175 Z" fill="#FEF08A" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" {{ $attributes }}>
|
||||||
|
<path d="M12 2C12.5 7.5 16.5 11.5 22 12C16.5 12.5 12.5 16.5 12 22C11.5 16.5 7.5 12.5 2 12C7.5 11.5 11.5 7.5 12 2Z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 228 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" {{ $attributes }}>
|
||||||
|
<path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 220 B |
@@ -0,0 +1,11 @@
|
|||||||
|
<div class="w-full rounded-[20px] p-4 bg-[#F5F7FA] border border-[#E2E8F0] shadow-sm flex items-center gap-4">
|
||||||
|
<div class="flex-1">
|
||||||
|
<h4 class="font-bold text-[#1E293B] text-[14px] mb-1.5">Bạn có biết?</h4>
|
||||||
|
<p class="text-[12px] text-[#475569] font-medium leading-relaxed">
|
||||||
|
Một lời cảm ơn chân thành có thể nhân đôi động lực làm việc của đồng nghiệp!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="w-6 h-6 bg-white rounded-full flex items-center justify-center shrink-0 shadow-sm border border-[#E2E8F0]">
|
||||||
|
<span class="text-lg drop-shadow-sm">💡</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<div class="absolute inset-0 pointer-events-none overflow-hidden z-0 select-none">
|
||||||
|
<svg class="absolute bottom-0 left-0 w-[45%] h-[40%] min-w-[320px] max-w-[600px] text-primary/[0.04]" viewBox="0 0 100 100" preserveAspectRatio="none" fill="currentColor" aria-hidden="true">
|
||||||
|
<path d="M 0,100 C 30,85 55,60 70,30 C 85,10 95,5 100,0 L 0,0 Z" transform="rotate(180, 50, 50)" />
|
||||||
|
<path d="M 0,100 C 40,75 60,50 75,25 C 90,5 95,0 100,0 L 0,0 Z" transform="rotate(180, 50, 50)" opacity="0.5" />
|
||||||
|
</svg>
|
||||||
|
<svg class="absolute top-10 right-10 w-[180px] h-[180px] text-primary/[0.03]" viewBox="0 0 100 100" fill="currentColor" aria-hidden="true">
|
||||||
|
<circle cx="10" cy="10" r="1.5" /> <circle cx="30" cy="10" r="1.5" /> <circle cx="50" cy="10" r="1.5" /> <circle cx="70" cy="10" r="1.5" /> <circle cx="90" cy="10" r="1.5" />
|
||||||
|
<circle cx="10" cy="30" r="1.5" /> <circle cx="30" cy="30" r="1.5" /> <circle cx="50" cy="30" r="1.5" /> <circle cx="70" cy="30" r="1.5" /> <circle cx="90" cy="30" r="1.5" />
|
||||||
|
<circle cx="10" cy="50" r="1.5" /> <circle cx="30" cy="50" r="1.5" /> <circle cx="50" cy="50" r="1.5" /> <circle cx="70" cy="50" r="1.5" /> <circle cx="90" cy="50" r="1.5" />
|
||||||
|
<circle cx="10" cy="70" r="1.5" /> <circle cx="30" cy="70" r="1.5" /> <circle cx="50" cy="70" r="1.5" /> <circle cx="70" cy="70" r="1.5" /> <circle cx="90" cy="70" r="1.5" />
|
||||||
|
<circle cx="10" cy="90" r="1.5" /> <circle cx="30" cy="90" r="1.5" /> <circle cx="50" cy="90" r="1.5" /> <circle cx="70" cy="90" r="1.5" /> <circle cx="90" cy="90" r="1.5" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<div class="flex-1 hidden lg:flex justify-center items-center relative min-h-[480px]">
|
||||||
|
<div class="relative z-10 w-full max-w-[440px]">
|
||||||
|
<svg viewBox="0 0 500 500" class="w-full h-auto" aria-hidden="true" role="img">
|
||||||
|
<circle cx="250" cy="250" r="180" fill="none" stroke="#e2e8f0" stroke-width="2" stroke-dasharray="6,6" opacity="0.6" />
|
||||||
|
|
||||||
|
<rect x="60" y="80" width="120" height="70" rx="4" fill="none" stroke="#cbd5e1" stroke-width="2" />
|
||||||
|
<line x1="60" y1="120" x2="180" y2="120" stroke="#cbd5e1" stroke-width="2" />
|
||||||
|
<rect x="75" y="95" width="12" height="25" fill="#94a3b8" />
|
||||||
|
<rect x="90" y="90" width="14" height="30" fill="#cbd5e1" />
|
||||||
|
<rect x="110" y="100" width="14" height="20" fill="#94a3b8" transform="rotate(15, 110, 100)" />
|
||||||
|
|
||||||
|
<rect x="340" y="60" width="100" height="130" rx="6" fill="none" stroke="#cbd5e1" stroke-width="2" />
|
||||||
|
<line x1="390" y1="60" x2="390" y2="190" stroke="#cbd5e1" stroke-width="1.5" />
|
||||||
|
<line x1="340" y1="120" x2="440" y2="120" stroke="#cbd5e1" stroke-width="1.5" />
|
||||||
|
|
||||||
|
<ellipse cx="250" cy="455" rx="55" ry="9" fill="#cbd5e1" opacity="0.4" />
|
||||||
|
|
||||||
|
<line x1="230" y1="360" x2="215" y2="450" stroke="#d29a0f" stroke-width="4.5" stroke-linecap="round" />
|
||||||
|
<line x1="270" y1="360" x2="285" y2="450" stroke="#d29a0f" stroke-width="4.5" stroke-linecap="round" />
|
||||||
|
<line x1="250" y1="360" x2="250" y2="450" stroke="#9a6a00" stroke-width="3.5" stroke-linecap="round" />
|
||||||
|
<ellipse cx="250" cy="415" rx="20" ry="4" fill="none" stroke="#d29a0f" stroke-width="2" />
|
||||||
|
<ellipse cx="250" cy="435" rx="24" ry="5" fill="none" stroke="#d29a0f" stroke-width="2" />
|
||||||
|
<rect x="220" y="348" width="60" height="12" rx="5" fill="#fbbf24" />
|
||||||
|
|
||||||
|
<polygon points="150,450 170,450 166,415 154,415" fill="#94a3b8" />
|
||||||
|
<path d="M 160,415 Q 145,390 135,385" fill="none" stroke="#cbd5e1" stroke-width="2.5" stroke-linecap="round" />
|
||||||
|
<path d="M 160,415 Q 165,380 175,370" fill="none" stroke="#cbd5e1" stroke-width="2.5" stroke-linecap="round" />
|
||||||
|
<circle cx="135" cy="385" r="7" fill="#cbd5e1" />
|
||||||
|
<circle cx="175" cy="370" r="9" fill="#94a3b8" />
|
||||||
|
|
||||||
|
<path d="M 230,358 Q 220,400 225,435" fill="none" stroke="#334155" stroke-width="12" stroke-linecap="round" />
|
||||||
|
<path d="M 252,358 Q 262,400 258,435" fill="none" stroke="#334155" stroke-width="12" stroke-linecap="round" />
|
||||||
|
<path d="M 225,435 L 218,443 L 230,443 Z" fill="#fbbf24" stroke="#fbbf24" stroke-width="3" stroke-linejoin="round" />
|
||||||
|
<path d="M 258,435 L 265,443 L 253,443 Z" fill="#fbbf24" stroke="#fbbf24" stroke-width="3" stroke-linejoin="round" />
|
||||||
|
|
||||||
|
<path d="M 222,275 C 222,275 258,275 258,275 L 252,325 C 252,325 228,325 228,325 Z" fill="#ffffff" />
|
||||||
|
<rect x="242" y="285" width="8" height="10" rx="1.5" fill="#ef222e" />
|
||||||
|
|
||||||
|
<rect x="235" y="260" width="10" height="16" fill="#fed7aa" />
|
||||||
|
|
||||||
|
<circle cx="240" cy="242" r="16" fill="#fed7aa" />
|
||||||
|
<circle cx="236" cy="240" r="18" fill="#1e293b" />
|
||||||
|
<path d="M 220,245 C 205,245 195,255 198,270 C 208,265 218,255 222,250 Z" fill="#1e293b" />
|
||||||
|
<path d="M 226,232 Q 242,225 252,238 C 252,238 246,228 234,228 Z" fill="#1e293b" />
|
||||||
|
<path d="M 228,230 Q 240,223 248,232" fill="none" stroke="#fbbf24" stroke-width="3.5" stroke-linecap="round" />
|
||||||
|
|
||||||
|
<polygon points="270,305 305,305 295,332 260,332" fill="#e2e8f0" />
|
||||||
|
<polygon points="273,308 302,308 293,329 264,329" fill="#0f4c81" opacity="0.1" />
|
||||||
|
<polygon points="252,332 295,332 290,338 247,338" fill="#cbd5e1" />
|
||||||
|
|
||||||
|
<path d="M 222,275 Q 240,312 265,315" fill="none" stroke="#fed7aa" stroke-width="7" stroke-linecap="round" />
|
||||||
|
<path d="M 242,275 Q 255,295 272,300" fill="none" stroke="#fed7aa" stroke-width="7" stroke-linecap="round" />
|
||||||
|
<circle cx="265" cy="315" r="4.5" fill="#fed7aa" />
|
||||||
|
<circle cx="272" cy="300" r="4.5" fill="#fed7aa" />
|
||||||
|
|
||||||
|
<g transform="translate(45, -20)">
|
||||||
|
<path d="M 266,160 C 266,120 305,100 335,120 C 355,130 365,150 365,170 C 365,190 345,210 325,205 L 312,222 L 309,204 C 282,198 266,180 266,160 Z" fill="#ffffff" filter="drop-shadow(0 4px 6px rgba(0,0,0,0.06))" />
|
||||||
|
|
||||||
|
<g transform="translate(302, 138)">
|
||||||
|
<path d="M 8,10 L 8,6 C 8,2.5 18,2.5 18,6 L 18,10" stroke="#0f4c81" stroke-width="2.5" stroke-linecap="round" fill="none" />
|
||||||
|
<rect x="3" y="10" width="20" height="15" rx="3.5" fill="#fbbf24" />
|
||||||
|
<circle cx="13" cy="16.5" r="1.5" fill="#0f4c81" />
|
||||||
|
<line x1="13" y1="18" x2="13" y2="21" stroke="#0f4c81" stroke-width="1.8" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<div class="bg-white rounded-2xl p-6 border border-gray-100 shadow-[0_2px_10px_-4px_rgba(0,0,0,0.05)] h-full flex flex-col justify-between">
|
||||||
|
<div>
|
||||||
|
<div class="flex items-center justify-between mb-1">
|
||||||
|
<h3 class="text-[16px] font-bold text-gray-900">Gửi nhanh</h3>
|
||||||
|
<button class="text-gray-300 hover:text-gray-500">
|
||||||
|
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p class="text-[12px] text-gray-400 font-medium mb-5">Chọn thiệp và gửi lời cảm ơn đến đồng nghiệp</p>
|
||||||
|
|
||||||
|
<!-- 3 Cards Grid -->
|
||||||
|
<div class="grid grid-cols-3 gap-2.5 mb-5">
|
||||||
|
<!-- Card 1 -->
|
||||||
|
<button class="rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-shadow border border-pink-50 relative group bg-gradient-to-b from-pink-50 to-pink-100/50 aspect-[2/3] flex items-center justify-center">
|
||||||
|
<div class="w-12 h-12 bg-white rounded-full flex items-center justify-center text-pink-400 text-xl shadow-sm mb-2 group-hover:scale-110 transition-transform">
|
||||||
|
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Card 2 -->
|
||||||
|
<button class="rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-shadow border border-blue-50 relative group bg-gradient-to-b from-blue-50 to-blue-100/50 aspect-[2/3] flex items-center justify-center">
|
||||||
|
<div class="w-12 h-12 bg-white rounded-full flex items-center justify-center text-blue-400 text-xl shadow-sm mb-2 group-hover:scale-110 transition-transform">
|
||||||
|
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Card 3 -->
|
||||||
|
<button class="rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-shadow border border-indigo-50 relative group bg-gradient-to-b from-indigo-50 to-indigo-100/50 aspect-[2/3] flex items-center justify-center">
|
||||||
|
<div class="w-12 h-12 bg-white rounded-full flex items-center justify-center text-indigo-400 text-xl shadow-sm mb-2 group-hover:scale-110 transition-transform">
|
||||||
|
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24"><path d="M12 2L1 21h22L12 2zm0 3.83L19.17 19H4.83L12 5.83z"/></svg>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Link -->
|
||||||
|
<a href="{{ route('user.send') }}" class="text-[13px] font-bold text-[#3462f7] hover:text-blue-800 flex items-center gap-1.5 group">
|
||||||
|
Tạo thiệp của riêng bạn
|
||||||
|
<svg class="w-3 h-3 transform group-hover:translate-x-1 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="3">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
@props(['rank', 'name', 'team', 'avatar', 'score', 'isCurrent' => false, 'unit' => 'điểm'])
|
||||||
|
|
||||||
|
<div class="flex items-center justify-between py-3 border-b border-gray-50 last:border-0 hover:bg-gray-50 rounded-xl px-3 transition-colors {{ $isCurrent ? 'bg-blue-50/50' : '' }}">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<!-- Rank -->
|
||||||
|
<div class="w-6 flex justify-center items-center">
|
||||||
|
@if($rank == 1)
|
||||||
|
<span class="text-xl">👑</span>
|
||||||
|
<span class="absolute text-[10px] font-bold text-amber-500 translate-y-3">1</span>
|
||||||
|
@elseif($rank == 2)
|
||||||
|
<span class="text-[14px] text-gray-500 font-bold">2</span>
|
||||||
|
@elseif($rank == 3)
|
||||||
|
<span class="text-[14px] text-gray-500 font-bold">3</span>
|
||||||
|
@else
|
||||||
|
<span class="text-[14px] font-bold {{ $isCurrent ? 'text-blue-600' : 'text-gray-400' }}">{{ $rank }}</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Avatar & Info -->
|
||||||
|
<div class="flex items-center gap-3 ml-1">
|
||||||
|
<img src="{{ $avatar }}" alt="{{ $name }}" class="w-9 h-9 rounded-full object-cover shadow-sm">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="text-[13px] font-bold {{ $isCurrent ? 'text-gray-900' : 'text-gray-800' }} leading-tight mb-0.5">{{ $name }}</span>
|
||||||
|
<span class="text-[11px] text-gray-400 font-medium">{{ $team }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Score -->
|
||||||
|
<div class="text-[13px]">
|
||||||
|
<span class="font-extrabold {{ $isCurrent ? 'text-blue-600' : 'text-gray-700' }}">{{ number_format($score, 0, ',', '.') }}</span>
|
||||||
|
<span class="text-gray-400 font-medium ml-0.5">{{ $unit }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
@props(['active' => false, 'icon' => 'home', 'href' => '#'])
|
||||||
|
|
||||||
|
@php
|
||||||
|
$classes = $active
|
||||||
|
? 'flex items-center gap-4 px-4 py-3 rounded-xl bg-[#eff4ff] text-[#3462f7] font-semibold transition-all duration-200'
|
||||||
|
: 'flex items-center gap-4 px-4 py-3 rounded-xl text-gray-500 hover:bg-gray-50 hover:text-gray-900 font-medium transition-all duration-200';
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<a href="{{ $href }}" {{ $attributes->merge(['class' => $classes]) }}>
|
||||||
|
@if($icon == 'home')
|
||||||
|
<svg class="w-[22px] h-[22px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
|
||||||
|
</svg>
|
||||||
|
@elseif($icon == 'paper-plane-send')
|
||||||
|
<svg class="w-[22px] h-[22px] transform -rotate-45" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
|
||||||
|
</svg>
|
||||||
|
@elseif($icon == 'heart')
|
||||||
|
<svg class="w-[22px] h-[22px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
|
||||||
|
</svg>
|
||||||
|
@elseif($icon == 'paper-plane-outline')
|
||||||
|
<svg class="w-[22px] h-[22px] transform -rotate-45" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
|
||||||
|
</svg>
|
||||||
|
@elseif($icon == 'trophy')
|
||||||
|
<svg class="w-[22px] h-[22px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M16 8v8m-4-5v5m-4-2v2m-2 4h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||||
|
</svg>
|
||||||
|
@elseif($icon == 'folder')
|
||||||
|
<svg class="w-[22px] h-[22px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
|
||||||
|
</svg>
|
||||||
|
@elseif($icon == 'chart')
|
||||||
|
<svg class="w-[22px] h-[22px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
|
||||||
|
</svg>
|
||||||
|
@elseif($icon == 'users')
|
||||||
|
<svg class="w-[22px] h-[22px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" />
|
||||||
|
</svg>
|
||||||
|
@elseif($icon == 'gear')
|
||||||
|
<svg class="w-[22px] h-[22px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||||
|
</svg>
|
||||||
|
@endif
|
||||||
|
<span class="text-[14px]">{{ $slot }}</span>
|
||||||
|
</a>
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
@props(['active' => false])
|
||||||
|
|
||||||
|
<aside class="sidebar flex flex-col h-full bg-white border-r border-gray-100 shadow-sm transition-transform duration-300 w-64 fixed inset-y-0 left-0 z-40 lg:relative lg:translate-x-0 -translate-x-full" aria-label="Main navigation">
|
||||||
|
<div class="p-6 flex items-center justify-between shrink-0">
|
||||||
|
<img src="{{ asset('images/logo.png') }}" alt="GMO-Z.com RUNSYSTEM" class="h-6 w-auto object-contain">
|
||||||
|
<!-- Mobile hamburger button/close -->
|
||||||
|
<button id="sidebar-close" class="lg:hidden p-2 text-gray-500 hover:bg-gray-100 rounded-md focus:outline-none" aria-label="Close navigation">
|
||||||
|
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="px-4 space-y-1.5 overflow-y-auto flex-1 pb-4">
|
||||||
|
<!-- TABS CHUNG -->
|
||||||
|
<x-sidebar-item href="{{ route('user.dashboard') }}" :active="request()->routeIs('user.dashboard')" icon="home">
|
||||||
|
Trang chủ
|
||||||
|
</x-sidebar-item>
|
||||||
|
|
||||||
|
<x-sidebar-item href="{{ route('user.send') }}" :active="request()->routeIs('user.send')" icon="paper-plane-send">
|
||||||
|
Gửi Thanks card
|
||||||
|
</x-sidebar-item>
|
||||||
|
|
||||||
|
<x-sidebar-item href="{{ route('user.received') }}" :active="request()->routeIs('user.received')" icon="heart">
|
||||||
|
Thanks đã nhận
|
||||||
|
</x-sidebar-item>
|
||||||
|
|
||||||
|
<x-sidebar-item href="{{ route('user.sent') }}" :active="request()->routeIs('user.sent')" icon="paper-plane-outline">
|
||||||
|
Thanks đã gửi
|
||||||
|
</x-sidebar-item>
|
||||||
|
|
||||||
|
<x-sidebar-item href="{{ route('user.ranking') }}" :active="request()->routeIs('user.ranking')" icon="trophy">
|
||||||
|
Bảng xếp hạng
|
||||||
|
</x-sidebar-item>
|
||||||
|
|
||||||
|
|
||||||
|
@if(Auth::check() && Auth::user()->role == \App\Models\User::ROLE_ADMIN)
|
||||||
|
<!-- ADMIN SIDEBAR -->
|
||||||
|
<div class="pt-2 mt-2 border-t border-gray-100"></div>
|
||||||
|
<x-sidebar-item href="{{ route('admin.users.index') }}" :active="request()->routeIs('admin.users.index')" icon="users">
|
||||||
|
Quản lý User
|
||||||
|
</x-sidebar-item>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<x-sidebar-item href="{{ route('user.change_password') }}" :active="request()->routeIs('user.change_password')" icon="gear">
|
||||||
|
Cài đặt
|
||||||
|
</x-sidebar-item>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- Illustration Box -->
|
||||||
|
<div class="hidden xl:flex justify-center items-center px-6 py-2 mt-auto">
|
||||||
|
<img src="{{ asset('images/sidebar_illustration.png') }}" class="w-full max-w-[200px] h-auto object-contain mix-blend-multiply" alt="Illustration" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- User Profile Section -->
|
||||||
|
<div class="p-5 border-t border-gray-100 flex items-center justify-between cursor-pointer hover:bg-gray-50 transition-colors shrink-0">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-full overflow-hidden shrink-0 border border-gray-200">
|
||||||
|
<img src="https://api.dicebear.com/7.x/notionists/svg?seed={{ Auth::id() ?? 'MinhAnh' }}&backgroundColor=e2e8f0" alt="Avatar" class="w-full h-full object-cover">
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="text-[14px] font-bold text-[#1e293b] leading-tight truncate max-w-[130px]">{{ Auth::check() ? (Auth::user()->name ?? 'Nguyễn Minh Anh') : 'Nguyễn Minh Anh' }}</span>
|
||||||
|
<span class="text-[12px] text-gray-500 font-medium">{{ Auth::check() ? (Auth::user()->role == \App\Models\User::ROLE_ADMIN ? 'Administrator' : 'Product Team') : 'Product Team' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<svg class="w-4 h-4 text-gray-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
@@ -1,14 +1,34 @@
|
|||||||
@props(['title', 'user', 'value', 'bgClass' => 'bg-[#0f4c81]', 'valueLabel' => 'Tổng thẻ đã nhận'])
|
@props(['title' => '', 'value' => '', 'growth' => '', 'growthType' => 'up', 'iconBgClass' => '', 'iconColorClass' => '', 'subtitle' => ''])
|
||||||
|
|
||||||
<div class="card-stat-active {{ $bgClass }}">
|
<div class="bg-white rounded-2xl p-5 md:p-6 border border-gray-100 shadow-[0_2px_10px_-4px_rgba(0,0,0,0.05)] hover:shadow-md transition-shadow h-full flex flex-col justify-center">
|
||||||
<div class="space-y-2">
|
<div class="flex items-center gap-5">
|
||||||
<div class="flex justify-between items-center">
|
<!-- Icon -->
|
||||||
<span class="text-white/90 text-xs font-bold uppercase tracking-wider">{{ $title }}</span>
|
<div class="w-[52px] h-[52px] rounded-2xl flex items-center justify-center shrink-0 {{ $iconBgClass }}">
|
||||||
<span class="text-2xl font-black">{{ $user && $value > 0 ? $user : 'Chưa có' }}</span>
|
<div class="{{ $iconColorClass }}">
|
||||||
|
{{ $slot }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between items-center pt-2 border-t border-white/20">
|
|
||||||
<span class="text-white/80 text-[10px] font-bold">{{ $valueLabel }}</span>
|
<!-- Content -->
|
||||||
<span class="text-lg font-bold text-yellow-300">{{ $value }} thẻ</span>
|
<div class="flex flex-col">
|
||||||
|
<span class="text-[13px] font-semibold text-gray-500 mb-1.5">{{ $title }}</span>
|
||||||
|
<div class="flex items-end gap-3 mb-1">
|
||||||
|
<span class="text-[34px] font-bold text-[#1e293b] leading-none">{{ $value }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if($growth)
|
||||||
|
<div class="flex items-center gap-1.5 mt-1">
|
||||||
|
<span class="flex items-center text-[12px] font-bold {{ $growthType === 'up' ? 'text-[#10b981]' : 'text-[#ef4444]' }}">
|
||||||
|
@if($growthType === 'up')
|
||||||
|
<svg class="w-3.5 h-3.5 mr-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="3"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5L12 3m0 0l7.5 7.5M12 3v18"/></svg>
|
||||||
|
@else
|
||||||
|
<svg class="w-3.5 h-3.5 mr-0.5 transform rotate-180" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="3"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5L12 3m0 0l7.5 7.5M12 3v18"/></svg>
|
||||||
|
@endif
|
||||||
|
{{ $growth }}
|
||||||
|
</span>
|
||||||
|
<span class="text-[11px] text-gray-400 font-medium">{{ $subtitle }}</span>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
@props(['title', 'message', 'isLiked' => false, 'bgClass', 'titleColorClass', 'textColorClass'])
|
||||||
|
|
||||||
|
<div class="rounded-[20px] p-5 border border-gray-100 shadow-sm {{ $bgClass }} transition-transform hover:-translate-y-1 hover:shadow-lg w-full">
|
||||||
|
<h4 class="text-center font-black text-[18px] text-[#1E293B] uppercase tracking-wider mb-3">
|
||||||
|
@if(str_contains($title, 'GREAT JOB'))
|
||||||
|
✨ {{ $title }} ✨
|
||||||
|
@elseif(str_contains($title, 'YOU ROCK'))
|
||||||
|
🌟 {{ $title }} 🌟
|
||||||
|
@else
|
||||||
|
💖 {{ $title }} 💖
|
||||||
|
@endif
|
||||||
|
</h4>
|
||||||
|
<p class="text-left text-[13px] text-[#475569] font-semibold leading-relaxed italic px-2">
|
||||||
|
"{{ $message }}"
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
@@ -1,419 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="vi">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
|
||||||
<title>GMO-Z.com RUNSYSTEM - Dashboard</title>
|
|
||||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
|
||||||
</head>
|
|
||||||
<body class="bg-bg-main text-text-dark font-sans antialiased">
|
|
||||||
<div class="app-layout">
|
|
||||||
<aside class="sidebar">
|
|
||||||
<div class="flex flex-col h-full justify-between">
|
|
||||||
<div>
|
|
||||||
<div class="h-16 flex items-center justify-between px-6 border-b border-border-light">
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<img src="{{ asset('images/logo.png') }}" alt="GMO-Z.com RUNSYSTEM" class="h-8 w-auto object-contain">
|
|
||||||
</div>
|
|
||||||
<button class="text-text-light hover:text-primary">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<nav class="p-4 space-y-1">
|
|
||||||
<a href="#" class="sidebar-link sidebar-link-active">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
|
|
||||||
</svg>
|
|
||||||
<span>DashBoard</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<div class="relative">
|
|
||||||
<a href="#" class="sidebar-link justify-between">
|
|
||||||
<span class="flex items-center gap-3">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
||||||
</svg>
|
|
||||||
<span>Chấm công</span>
|
|
||||||
</span>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-4 h-4">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a href="#" class="sidebar-link">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" />
|
|
||||||
</svg>
|
|
||||||
<span>Danh sách khóa học</span>
|
|
||||||
</a>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div class="mx-4 my-2 p-4 rounded-lg bg-primary/5 border border-primary/10 flex flex-col items-center text-center">
|
|
||||||
<img src="https://illustrations.popsy.co/blue/document-delivery.svg" alt="Support" class="w-24 h-24 object-contain mb-2">
|
|
||||||
<h4 class="text-text-dark font-semibold text-xs mb-1">Bạn có thắc mắc về ngày công?</h4>
|
|
||||||
<a href="#" class="btn-primary py-1.5 px-4 text-xs w-full mt-2 inline-block">Phản hồi</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="px-6 py-4 border-t border-border-light text-center">
|
|
||||||
<span class="text-text-muted text-[10px]">© 2026 GMO-Z.com RUNSYSTEM</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
<main class="main-content">
|
|
||||||
<header class="top-header">
|
|
||||||
<div class="flex items-center gap-3 overflow-x-auto py-2">
|
|
||||||
<span class="text-text-light text-xs font-bold whitespace-nowrap">Link liên kết:</span>
|
|
||||||
<a href="#" class="border border-border-medium rounded px-2.5 py-1 text-xs text-text-medium hover:text-primary relative font-medium whitespace-nowrap">
|
|
||||||
RUN AI <span class="nav-badge">NEW!</span>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="border border-border-medium rounded px-2.5 py-1 text-xs text-text-medium hover:text-primary relative font-medium whitespace-nowrap">
|
|
||||||
G-Office <span class="nav-badge">NEW!</span>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="border border-border-medium rounded px-2.5 py-1 text-xs text-text-medium hover:text-primary relative font-medium whitespace-nowrap">
|
|
||||||
RUN Helpline <span class="nav-badge">NEW!</span>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="border border-border-medium rounded px-2.5 py-1 text-xs text-text-medium hover:text-primary font-medium whitespace-nowrap">JIRA8</a>
|
|
||||||
<a href="#" class="border border-border-medium rounded px-2.5 py-1 text-xs text-text-medium hover:text-primary font-medium whitespace-nowrap">WE</a>
|
|
||||||
<a href="#" class="border border-border-medium rounded px-2.5 py-1 text-xs text-text-medium hover:text-primary font-medium whitespace-nowrap">G-Help</a>
|
|
||||||
<a href="#" class="border border-border-medium rounded px-2.5 py-1 text-xs text-text-medium hover:text-primary font-medium whitespace-nowrap">G-Booking</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center gap-4 shrink-0">
|
|
||||||
<button class="relative text-text-medium hover:text-primary p-1.5 rounded-full hover:bg-gray-100 transition-colors">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-6 h-6">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" />
|
|
||||||
</svg>
|
|
||||||
<span class="notification-badge">1</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div class="flex items-center gap-2 border-l border-border-light pl-4">
|
|
||||||
<div class="w-8 h-8 rounded-full bg-primary-light text-primary flex items-center justify-center font-bold text-sm">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5 text-primary">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<span class="text-xs font-bold text-text-dark">TRẦN VĂN AN</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="flex-1 overflow-y-auto p-6 space-y-6">
|
|
||||||
<div class="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
|
||||||
<h2 class="text-xl font-bold text-text-dark flex items-center gap-2">
|
|
||||||
Bảng chấm công
|
|
||||||
</h2>
|
|
||||||
<div class="flex flex-wrap items-center gap-4 text-xs font-semibold">
|
|
||||||
<a href="#" class="text-secondary hover:underline flex items-center gap-1.5">
|
|
||||||
👉 Quy định chấm công, nghỉ phép
|
|
||||||
</a>
|
|
||||||
<a href="#" class="text-secondary hover:underline flex items-center gap-1.5">
|
|
||||||
👉 Quy định chấm công, nghỉ phép HCM
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
||||||
<div class="card-stat-active">
|
|
||||||
<div class="space-y-2">
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-white/80 text-xs font-bold">Ngày công chuẩn</span>
|
|
||||||
<span class="text-xl font-bold">22</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-between items-center pt-2 border-t border-white/10">
|
|
||||||
<span class="text-white/80 text-xs font-bold">Ngày công lễ</span>
|
|
||||||
<span class="text-xl font-bold">0</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-stat">
|
|
||||||
<div class="space-y-2">
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-text-medium text-xs font-bold">Ngày công thực tế</span>
|
|
||||||
<span class="text-xl font-bold">20</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-between items-center pt-2 border-t border-border-light">
|
|
||||||
<span class="text-text-medium text-xs font-bold">Nghỉ phép</span>
|
|
||||||
<span class="text-xl font-bold">0</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-stat">
|
|
||||||
<div class="space-y-2">
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-text-medium text-xs font-bold">Số lần đi muộn, về sớm</span>
|
|
||||||
<span class="text-xl font-bold text-red-500">0</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-between items-center pt-2 border-t border-border-light">
|
|
||||||
<span class="text-text-medium text-xs font-bold">Số giờ đi muộn, về sớm</span>
|
|
||||||
<span class="text-xl font-bold">0</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-stat">
|
|
||||||
<div class="space-y-1.5">
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-text-medium text-xs font-bold">Số giờ OT 150%</span>
|
|
||||||
<span class="text-sm font-bold">0</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-text-medium text-xs font-bold">Số giờ OT 200%</span>
|
|
||||||
<span class="text-sm font-bold">0</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<span class="text-text-medium text-xs font-bold">Số giờ OT 300%</span>
|
|
||||||
<span class="text-sm font-bold">0</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="space-y-4">
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<div class="flex items-center gap-4 text-primary font-bold">
|
|
||||||
<button class="p-1 hover:bg-gray-100 rounded transition-colors">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<span class="text-lg">Tháng 06/2026</span>
|
|
||||||
<button class="p-1 hover:bg-gray-100 rounded transition-colors">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center border border-border-medium rounded-lg overflow-hidden bg-white">
|
|
||||||
<button class="p-2 bg-primary-light text-primary hover:bg-primary/10 transition-colors border-r border-border-light">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5m-9-6h.008v.008H12v-.008zM12 15h.008v.008H12V15zm0 2.25h.008v.008H12v-.008zM9.75 15h.008v.008H9.75V15zm0 2.25h.008v.008H9.75v-.008zM7.5 15h.008v.008H7.5V15zm0 2.25h.008v.008H7.5v-.008zm6.75-4.5h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V15zm0 2.25h.008v.008h-.008v-.008zm2.25-4.5h.008v.008H16.5v-.008zm0 2.25h.008v.008H16.5V15z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button class="p-2 hover:bg-gray-50 text-text-medium transition-colors">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 6.75h12M8.25 12h12M8.25 17.25h12M3.75 6.75h.007v.008H3.75V6.75zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zM3.75 12h.007v.008H3.75V12zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zM3.75 17.25h.007v.008H3.75v-.008zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="calendar-card">
|
|
||||||
<div class="calendar-header">
|
|
||||||
<div>Thứ 2</div>
|
|
||||||
<div>Thứ 3</div>
|
|
||||||
<div>Thứ 4</div>
|
|
||||||
<div>Thứ 5</div>
|
|
||||||
<div>Thứ 6</div>
|
|
||||||
<div>Thứ 7</div>
|
|
||||||
<div>CN</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="calendar-grid">
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">1</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:45 - 17:13</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:28</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">2</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:53 - 17:08</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:15</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">3</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:54 - 17:16</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:22</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">4</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:52 - 17:04</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:12</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">5</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:50 - 17:20</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:30</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day calendar-day-weekend">
|
|
||||||
<div class="flex justify-end">
|
|
||||||
<span class="text-xs font-semibold text-text-light">6</span>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day calendar-day-weekend">
|
|
||||||
<div class="flex justify-end">
|
|
||||||
<span class="text-xs font-semibold text-text-light">7</span>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">8</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:54 - 17:05</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:11</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">9</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:48 - 17:05</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:17</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">10</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:51 - 17:05</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:14</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">11</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:45 - 17:13</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:28</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">12</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:45 - 17:37</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:52</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day calendar-day-weekend">
|
|
||||||
<div class="flex justify-end">
|
|
||||||
<span class="text-xs font-semibold text-text-light">13</span>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day calendar-day-weekend">
|
|
||||||
<div class="flex justify-end">
|
|
||||||
<span class="text-xs font-semibold text-text-light">14</span>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">15</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:47 - 17:04</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:17</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">16</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:45 - 17:02</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:17</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">17</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:54 - 17:02</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:08</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">18</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:45 - 17:03</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:18</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day">
|
|
||||||
<div class="flex justify-between items-start">
|
|
||||||
<span class="text-lg font-extrabold text-primary">X</span>
|
|
||||||
<span class="text-xs font-semibold text-text-light">19</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="text-xs font-bold text-text-dark">07:45 - 17:04</div>
|
|
||||||
<div class="text-[10px] font-bold text-primary">+ 0:19</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day calendar-day-weekend">
|
|
||||||
<div class="flex justify-end">
|
|
||||||
<span class="text-xs font-semibold text-text-light">20</span>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<div class="calendar-day calendar-day-weekend">
|
|
||||||
<div class="flex justify-end">
|
|
||||||
<span class="text-xs font-semibold text-text-light">21</span>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -12,93 +12,12 @@
|
|||||||
<div class="app-layout">
|
<div class="app-layout">
|
||||||
<!-- Mobile overlay (click outside to close) -->
|
<!-- Mobile overlay (click outside to close) -->
|
||||||
<div id="sidebar-overlay" class="fixed inset-0 bg-black/30 hidden" aria-hidden="true"></div>
|
<div id="sidebar-overlay" class="fixed inset-0 bg-black/30 hidden" aria-hidden="true"></div>
|
||||||
<aside class="sidebar" aria-label="Main navigation">
|
<!-- Sidebar Component -->
|
||||||
<div class="flex flex-col h-full justify-between">
|
<x-sidebar />
|
||||||
<div class="flex-1 flex flex-col min-h-0 overflow-hidden">
|
|
||||||
<div class="h-16 flex items-center justify-between px-6 border-b border-border-light">
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<img src="{{ asset('images/logo.png') }}" alt="GMO-Z.com RUNSYSTEM" class="h-8 w-auto object-contain">
|
|
||||||
</div>
|
|
||||||
<!-- Collapse / Expand button (desktop) -->
|
|
||||||
<button id="sidebar-toggle" class="hidden lg:inline-flex p-2 focus:outline-none focus:ring-2 focus:ring-white" aria-label="Collapse sidebar" aria-controls="sidebar" aria-expanded="true">
|
|
||||||
<x-icon name="icn-chevron-left" class="w-5 h-5" />
|
|
||||||
</button>
|
|
||||||
<!-- Mobile hamburger button -->
|
|
||||||
<button id="sidebar-hamburger" class="lg:hidden p-2 focus:outline-none focus:ring-2 focus:ring-white" aria-label="Open navigation" aria-controls="sidebar" aria-expanded="false">
|
|
||||||
<x-icon name="icn-menu" class="w-5 h-5" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<nav class="p-4 space-y-1 overflow-y-auto flex-1">
|
<main class="main-content flex-1 flex flex-col h-full bg-[#f8faff] overflow-hidden relative w-full lg:w-auto">
|
||||||
@if(Auth::check() && Auth::user()->role == \App\Models\User::ROLE_ADMIN)
|
<!-- Header Component -->
|
||||||
<!-- ADMIN SIDEBAR -->
|
<x-header />
|
||||||
<a href="{{ route('admin.users.index') }}" class="sidebar-link {{ request()->routeIs('admin.users.index') ? 'sidebar-link-active' : '' }}">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" />
|
|
||||||
</svg>
|
|
||||||
<span>{{ __('layout.manage_users') }}</span>
|
|
||||||
</a>
|
|
||||||
<a href="{{ route('admin.users.create') }}" class="sidebar-link {{ request()->routeIs('admin.users.create') ? 'sidebar-link-active' : '' }}">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
|
||||||
</svg>
|
|
||||||
<span>{{ __('layout.add_user') }}</span>
|
|
||||||
</a>
|
|
||||||
@else
|
|
||||||
<!-- USER SIDEBAR -->
|
|
||||||
<a href="{{ route('user.dashboard') }}" class="sidebar-link {{ request()->routeIs('user.dashboard') ? 'sidebar-link-active' : '' }}">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
|
|
||||||
</svg>
|
|
||||||
<span>{{ __('layout.my_page') }}</span>
|
|
||||||
</a>
|
|
||||||
<a href="{{ route('user.send') }}" class="sidebar-link {{ request()->routeIs('user.send') ? 'sidebar-link-active' : '' }}">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 12L3.269 3.126A59.768 59.768 0 0121.485 12 59.77 59.77 0 013.27 20.876L5.999 12zm0 0h7.5" />
|
|
||||||
</svg>
|
|
||||||
<span>{{ __('layout.send_card') }}</span>
|
|
||||||
</a>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<a href="{{ route('user.change_password') }}" class="sidebar-link {{ request()->routeIs('user.change_password') ? 'sidebar-link-active' : '' }}">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0V10.5m-2.812 10.5h14.625c.621 0 1.125-.504 1.125-1.125V11.25c0-.621-.504-1.125-1.125-1.125H3.75c-.621 0-1.125.504-1.125 1.125v7.875c0 .621.504 1.125 1.125 1.125z" />
|
|
||||||
</svg>
|
|
||||||
<span>{{ __('layout.change_password') }}</span>
|
|
||||||
</a>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="shrink-0">
|
|
||||||
<div class="px-6 py-4 border-t border-border-light text-center">
|
|
||||||
<span class="text-text-muted text-[10px]">© 2026 GMO-Z.com RUNSYSTEM</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
<main class="main-content">
|
|
||||||
<header class="top-header">
|
|
||||||
<div class="flex items-center gap-3 overflow-x-auto py-2">
|
|
||||||
<span class="text-text-light text-xs font-bold whitespace-nowrap">Thank Card System</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center gap-4 shrink-0">
|
|
||||||
<div class="flex items-center gap-2 border-l border-border-light pl-4">
|
|
||||||
<div class="w-8 h-8 rounded-full bg-primary-light text-primary flex items-center justify-center font-bold text-sm">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5 text-primary">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<span class="text-xs font-bold text-text-dark">{{ Auth::check() ? Auth::user()->mail : 'GUEST' }}</span>
|
|
||||||
|
|
||||||
<form method="POST" action="{{ route('logout') }}" class="ml-2">
|
|
||||||
@csrf
|
|
||||||
<button type="submit" class="text-xs text-red-500 font-bold hover:underline">{{ __('layout.logout') }}</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="flex-1 overflow-y-auto p-6 space-y-6">
|
<div class="flex-1 overflow-y-auto p-6 space-y-6">
|
||||||
@if(session('success'))
|
@if(session('success'))
|
||||||
@@ -175,6 +94,32 @@
|
|||||||
document.body.style.overflow = '';
|
document.body.style.overflow = '';
|
||||||
}, 300); // 300ms matches Tailwind duration-300
|
}, 300); // 300ms matches Tailwind duration-300
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Mobile Sidebar Toggle Logic
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const hamburger = document.getElementById('sidebar-hamburger');
|
||||||
|
const closeBtn = document.getElementById('sidebar-close');
|
||||||
|
const overlay = document.getElementById('sidebar-overlay');
|
||||||
|
const sidebar = document.querySelector('.sidebar');
|
||||||
|
|
||||||
|
if (hamburger && sidebar && overlay && closeBtn) {
|
||||||
|
function openSidebar() {
|
||||||
|
sidebar.classList.remove('-translate-x-full');
|
||||||
|
overlay.classList.remove('hidden');
|
||||||
|
document.body.style.overflow = 'hidden';
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeSidebar() {
|
||||||
|
sidebar.classList.add('-translate-x-full');
|
||||||
|
overlay.classList.add('hidden');
|
||||||
|
document.body.style.overflow = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
hamburger.addEventListener('click', openSidebar);
|
||||||
|
closeBtn.addEventListener('click', closeSidebar);
|
||||||
|
overlay.addEventListener('click', closeSidebar);
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
@stack('scripts')
|
@stack('scripts')
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -5,242 +5,180 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||||
<title>GMO-Z.com RUNSYSTEM - {{ __('auth.login') }}</title>
|
<title>GMO-Z.com RUNSYSTEM - {{ __('auth.login') }}</title>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Caveat:wght@700&display=swap" rel="stylesheet">
|
||||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||||
<style>
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from { opacity: 0; }
|
|
||||||
to { opacity: 1; }
|
|
||||||
}
|
|
||||||
.animate-fade-in {
|
|
||||||
animation: fadeIn 0.3s ease-in-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.floating-group {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.floating-input {
|
|
||||||
width: 100%;
|
|
||||||
height: 56px;
|
|
||||||
padding-left: 2.75rem;
|
|
||||||
padding-right: 1rem;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
color: #1e293b;
|
|
||||||
background-color: transparent;
|
|
||||||
border: 1px solid #c4c4c4;
|
|
||||||
border-radius: 4px;
|
|
||||||
outline: none;
|
|
||||||
transition: all 0.2s ease-in-out;
|
|
||||||
}
|
|
||||||
.floating-input:hover {
|
|
||||||
border-color: #475569;
|
|
||||||
}
|
|
||||||
.floating-input:focus {
|
|
||||||
border: 2px solid #0f4c81;
|
|
||||||
padding-left: calc(2.75rem - 1px);
|
|
||||||
}
|
|
||||||
.floating-label {
|
|
||||||
position: absolute;
|
|
||||||
left: 2.75rem;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
color: #94a3b8;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
pointer-events: none;
|
|
||||||
transition: all 0.2s ease-in-out;
|
|
||||||
background-color: transparent;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.floating-input:focus ~ .floating-label,
|
|
||||||
.floating-input:not(:placeholder-shown) ~ .floating-label {
|
|
||||||
top: 0;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
font-size: 0.75rem;
|
|
||||||
color: #0f4c81;
|
|
||||||
background-color: #ffffff;
|
|
||||||
padding: 0 6px;
|
|
||||||
left: 2.5rem;
|
|
||||||
}
|
|
||||||
.floating-input:not(:focus):not(:placeholder-shown) ~ .floating-label {
|
|
||||||
color: #64748b;
|
|
||||||
}
|
|
||||||
.floating-icon {
|
|
||||||
position: absolute;
|
|
||||||
left: 1rem;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
color: #94a3b8;
|
|
||||||
pointer-events: none;
|
|
||||||
transition: color 0.2s ease-in-out;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
.floating-input:focus ~ .floating-icon {
|
|
||||||
color: #0f4c81;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="min-h-screen flex items-center justify-center font-sans antialiased overflow-x-hidden relative bg-gradient-to-br from-[#ffffff] via-[#f8fafc] to-[#eef2f6]">
|
<body class="min-h-screen flex items-center justify-center font-sans antialiased overflow-hidden relative bg-[#f0f4f9] p-4 sm:p-6 lg:p-10">
|
||||||
|
|
||||||
<div class="absolute inset-0 pointer-events-none overflow-hidden z-0 select-none">
|
<!-- Main Card -->
|
||||||
<svg class="absolute bottom-0 left-0 w-[45%] h-[40%] min-w-[320px] max-w-[600px] text-[#0f4c81]/[0.04]" viewBox="0 0 100 100" preserveAspectRatio="none" fill="currentColor">
|
<div class="w-full max-w-[1100px] bg-white rounded-[24px] shadow-2xl flex flex-col lg:flex-row overflow-hidden min-h-[650px] relative z-10">
|
||||||
<path d="M 0,100 C 30,85 55,60 70,30 C 85,10 95,5 100,0 L 0,0 Z" transform="rotate(180, 50, 50)" />
|
|
||||||
<path d="M 0,100 C 40,75 60,50 75,25 C 90,5 95,0 100,0 L 0,0 Z" transform="rotate(180, 50, 50)" opacity="0.5" />
|
|
||||||
</svg>
|
|
||||||
<svg class="absolute top-10 right-10 w-[180px] h-[180px] text-[#0f4c81]/[0.03]" viewBox="0 0 100 100" fill="currentColor">
|
|
||||||
<circle cx="10" cy="10" r="1.5" /> <circle cx="30" cy="10" r="1.5" /> <circle cx="50" cy="10" r="1.5" /> <circle cx="70" cy="10" r="1.5" /> <circle cx="90" cy="10" r="1.5" />
|
|
||||||
<circle cx="10" cy="30" r="1.5" /> <circle cx="30" cy="30" r="1.5" /> <circle cx="50" cy="30" r="1.5" /> <circle cx="70" cy="30" r="1.5" /> <circle cx="90" cy="30" r="1.5" />
|
|
||||||
<circle cx="10" cy="50" r="1.5" /> <circle cx="30" cy="50" r="1.5" /> <circle cx="50" cy="50" r="1.5" /> <circle cx="70" cy="50" r="1.5" /> <circle cx="90" cy="50" r="1.5" />
|
|
||||||
<circle cx="10" cy="70" r="1.5" /> <circle cx="30" cy="70" r="1.5" /> <circle cx="50" cy="70" r="1.5" /> <circle cx="70" cy="70" r="1.5" /> <circle cx="90" cy="70" r="1.5" />
|
|
||||||
<circle cx="10" cy="90" r="1.5" /> <circle cx="30" cy="90" r="1.5" /> <circle cx="50" cy="90" r="1.5" /> <circle cx="70" cy="90" r="1.5" /> <circle cx="90" cy="90" r="1.5" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="relative w-full max-w-6xl mx-auto px-6 flex flex-col lg:flex-row items-center justify-between gap-16 py-12 z-10">
|
<!-- LEFT COLUMN: Login Form -->
|
||||||
|
<div class="w-full lg:w-[50%] p-8 sm:p-12 lg:p-16 flex flex-col relative bg-white">
|
||||||
<div class="flex-1 flex flex-col items-center w-full">
|
<!-- Decorative Elements Left -->
|
||||||
<div class="relative w-full max-w-[620px] bg-[#263238] rounded-t-[16px] p-2 sm:p-4 shadow-2xl border border-slate-700/60 transition-all duration-300">
|
<!-- Heart icon -->
|
||||||
<div class="w-full bg-white rounded-[6px] overflow-hidden flex flex-col justify-between p-6 aspect-[16/10.5] min-h-[440px] relative shadow-inner">
|
<div class="absolute top-12 left-10 w-10 h-10 opacity-90 hidden sm:block">
|
||||||
|
<svg viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<div class="flex justify-start items-center">
|
<path d="M50 88C50 88 15 62 15 35C15 20 28 10 40 15C45 17 50 24 50 24C50 24 55 17 60 15C72 10 85 20 85 35C85 62 50 88 50 88Z" fill="#ff4d6d"/>
|
||||||
<img src="{{ asset('images/logo.png') }}" alt="GMO-Z.com RUNSYSTEM" class="h-8 w-auto object-contain">
|
<path d="M50 88C50 88 15 62 15 35C15 20 28 10 40 15C45 17 50 24 50 24C50 24 55 17 60 15C72 10 85 20 85 35C85 62 50 88 50 88Z" fill="url(#paint0_linear)" opacity="0.3"/>
|
||||||
</div>
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear" x1="15" y1="35" x2="85" y2="35" gradientUnits="userSpaceOnUse">
|
||||||
<div class="w-full max-w-[360px] mx-auto space-y-4 my-auto">
|
<stop stop-color="white"/>
|
||||||
<h3 class="text-xl font-bold text-center text-[#0f4c81] tracking-wide">{{ __('auth.login') }}</h3>
|
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
<form action="{{ route('login') }}" method="POST" class="space-y-4">
|
</defs>
|
||||||
@csrf
|
|
||||||
|
|
||||||
<div class="min-h-[52px] flex items-center justify-center transition-all duration-300" aria-live="polite">
|
|
||||||
@if($errors->any())
|
|
||||||
<div class="w-full bg-red-50 text-red-600 text-xs font-semibold p-2.5 rounded border border-red-200 shadow-sm flex items-start gap-2 animate-fade-in transition-opacity duration-300 ease-in-out opacity-100">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 shrink-0 mt-0.5 text-red-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
|
||||||
</svg>
|
|
||||||
<span class="leading-normal">{{ $errors->first() }}</span>
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
<div class="w-full opacity-0 pointer-events-none select-none" aria-hidden="true">
|
|
||||||
<div class="p-2.5 text-xs border border-transparent flex items-start gap-2">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24"></svg>
|
|
||||||
<span class="leading-normal"> </span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="floating-group">
|
|
||||||
<input type="email" name="mail" id="mail" placeholder=" " required value="{{ old('mail') }}" class="floating-input" />
|
|
||||||
<label for="mail" class="floating-label">
|
|
||||||
{{ __('auth.email') }} <span class="text-red-500">*</span>
|
|
||||||
</label>
|
|
||||||
<span class="floating-icon">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" />
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="floating-group">
|
|
||||||
<input type="password" name="password" id="password" placeholder=" " required class="floating-input" />
|
|
||||||
<label for="password" class="floating-label">
|
|
||||||
{{ __('auth.password') }} <span class="text-red-500">*</span>
|
|
||||||
</label>
|
|
||||||
<span class="floating-icon">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0V10.5m-2.812 10.5h14.625c.621 0 1.125-.504 1.125-1.125V11.25c0-.621-.504-1.125-1.125-1.125H3.75c-.621 0-1.125.504-1.125 1.125v7.875c0 .621.504 1.125 1.125 1.125z" />
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="w-full h-[48px] bg-[#0f4c81] hover:bg-[#0a3a63] text-white font-semibold rounded shadow-md hover:shadow-lg transition-all duration-200 tracking-wide uppercase text-sm cursor-pointer focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#0f4c81]">
|
|
||||||
{{ __('auth.login') }}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-center mt-auto">
|
|
||||||
<span class="text-[11px] text-slate-400 font-medium">© {{ __('auth.developed_by') }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="relative w-full max-w-[690px] h-2 sm:h-3 bg-[#b0bec5] rounded-b-[16px] border-t border-white/20 shadow-xl transition-all duration-300">
|
|
||||||
<div class="absolute left-1/2 -translate-x-1/2 top-0 w-20 sm:w-24 h-1 sm:h-1.5 bg-[#90a4ae] rounded-b-[4px]"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex-1 hidden lg:flex justify-center items-center relative min-h-[480px]">
|
|
||||||
<div class="relative z-10 w-full max-w-[440px]">
|
|
||||||
<svg viewBox="0 0 500 500" class="w-full h-auto">
|
|
||||||
<circle cx="250" cy="250" r="180" fill="none" stroke="#e2e8f0" stroke-width="2" stroke-dasharray="6,6" opacity="0.6" />
|
|
||||||
|
|
||||||
<rect x="60" y="80" width="120" height="70" rx="4" fill="none" stroke="#cbd5e1" stroke-width="2" />
|
|
||||||
<line x1="60" y1="120" x2="180" y2="120" stroke="#cbd5e1" stroke-width="2" />
|
|
||||||
<rect x="75" y="95" width="12" height="25" fill="#94a3b8" />
|
|
||||||
<rect x="90" y="90" width="14" height="30" fill="#cbd5e1" />
|
|
||||||
<rect x="110" y="100" width="14" height="20" fill="#94a3b8" transform="rotate(15, 110, 100)" />
|
|
||||||
|
|
||||||
<rect x="340" y="60" width="100" height="130" rx="6" fill="none" stroke="#cbd5e1" stroke-width="2" />
|
|
||||||
<line x1="390" y1="60" x2="390" y2="190" stroke="#cbd5e1" stroke-width="1.5" />
|
|
||||||
<line x1="340" y1="120" x2="440" y2="120" stroke="#cbd5e1" stroke-width="1.5" />
|
|
||||||
|
|
||||||
<ellipse cx="250" cy="455" rx="55" ry="9" fill="#cbd5e1" opacity="0.4" />
|
|
||||||
|
|
||||||
<line x1="230" y1="360" x2="215" y2="450" stroke="#d29a0f" stroke-width="4.5" stroke-linecap="round" />
|
|
||||||
<line x1="270" y1="360" x2="285" y2="450" stroke="#d29a0f" stroke-width="4.5" stroke-linecap="round" />
|
|
||||||
<line x1="250" y1="360" x2="250" y2="450" stroke="#9a6a00" stroke-width="3.5" stroke-linecap="round" />
|
|
||||||
<ellipse cx="250" cy="415" rx="20" ry="4" fill="none" stroke="#d29a0f" stroke-width="2" />
|
|
||||||
<ellipse cx="250" cy="435" rx="24" ry="5" fill="none" stroke="#d29a0f" stroke-width="2" />
|
|
||||||
<rect x="220" y="348" width="60" height="12" rx="5" fill="#fbbf24" />
|
|
||||||
|
|
||||||
<polygon points="150,450 170,450 166,415 154,415" fill="#94a3b8" />
|
|
||||||
<path d="M 160,415 Q 145,390 135,385" fill="none" stroke="#cbd5e1" stroke-width="2.5" stroke-linecap="round" />
|
|
||||||
<path d="M 160,415 Q 165,380 175,370" fill="none" stroke="#cbd5e1" stroke-width="2.5" stroke-linecap="round" />
|
|
||||||
<circle cx="135" cy="385" r="7" fill="#cbd5e1" />
|
|
||||||
<circle cx="175" cy="370" r="9" fill="#94a3b8" />
|
|
||||||
|
|
||||||
<path d="M 230,358 Q 220,400 225,435" fill="none" stroke="#334155" stroke-width="12" stroke-linecap="round" />
|
|
||||||
<path d="M 252,358 Q 262,400 258,435" fill="none" stroke="#334155" stroke-width="12" stroke-linecap="round" />
|
|
||||||
<path d="M 225,435 L 218,443 L 230,443 Z" fill="#fbbf24" stroke="#fbbf24" stroke-width="3" stroke-linejoin="round" />
|
|
||||||
<path d="M 258,435 L 265,443 L 253,443 Z" fill="#fbbf24" stroke="#fbbf24" stroke-width="3" stroke-linejoin="round" />
|
|
||||||
|
|
||||||
<path d="M 222,275 C 222,275 258,275 258,275 L 252,325 C 252,325 228,325 228,325 Z" fill="#ffffff" />
|
|
||||||
<rect x="242" y="285" width="8" height="10" rx="1.5" fill="#ef222e" />
|
|
||||||
|
|
||||||
<rect x="235" y="260" width="10" height="16" fill="#fed7aa" />
|
|
||||||
|
|
||||||
<circle cx="240" cy="242" r="16" fill="#fed7aa" />
|
|
||||||
<circle cx="236" cy="240" r="18" fill="#1e293b" />
|
|
||||||
<path d="M 220,245 C 205,245 195,255 198,270 C 208,265 218,255 222,250 Z" fill="#1e293b" />
|
|
||||||
<path d="M 226,232 Q 242,225 252,238 C 252,238 246,228 234,228 Z" fill="#1e293b" />
|
|
||||||
<path d="M 228,230 Q 240,223 248,232" fill="none" stroke="#fbbf24" stroke-width="3.5" stroke-linecap="round" />
|
|
||||||
|
|
||||||
<polygon points="270,305 305,305 295,332 260,332" fill="#e2e8f0" />
|
|
||||||
<polygon points="273,308 302,308 293,329 264,329" fill="#0f4c81" opacity="0.1" />
|
|
||||||
<polygon points="252,332 295,332 290,338 247,338" fill="#cbd5e1" />
|
|
||||||
|
|
||||||
<path d="M 222,275 Q 240,312 265,315" fill="none" stroke="#fed7aa" stroke-width="7" stroke-linecap="round" />
|
|
||||||
<path d="M 242,275 Q 255,295 272,300" fill="none" stroke="#fed7aa" stroke-width="7" stroke-linecap="round" />
|
|
||||||
<circle cx="265" cy="315" r="4.5" fill="#fed7aa" />
|
|
||||||
<circle cx="272" cy="300" r="4.5" fill="#fed7aa" />
|
|
||||||
|
|
||||||
<g transform="translate(45, -20)">
|
|
||||||
<path d="M 266,160 C 266,120 305,100 335,120 C 355,130 365,150 365,170 C 365,190 345,210 325,205 L 312,222 L 309,204 C 282,198 266,180 266,160 Z" fill="#ffffff" filter="drop-shadow(0 4px 6px rgba(0,0,0,0.06))" />
|
|
||||||
|
|
||||||
<g transform="translate(302, 138)">
|
|
||||||
<path d="M 8,10 L 8,6 C 8,2.5 18,2.5 18,6 L 18,10" stroke="#0f4c81" stroke-width="2.5" stroke-linecap="round" fill="none" />
|
|
||||||
<rect x="3" y="10" width="20" height="15" rx="3.5" fill="#fbbf24" />
|
|
||||||
<circle cx="13" cy="16.5" r="1.5" fill="#0f4c81" />
|
|
||||||
<line x1="13" y1="18" x2="13" y2="21" stroke="#0f4c81" stroke-width="1.8" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Star bottom left -->
|
||||||
|
<div class="absolute bottom-16 left-12 w-6 h-6 hidden sm:block">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M12 0L14.59 9.41L24 12L14.59 14.59L12 24L9.41 14.59L0 12L9.41 9.41L12 0Z" fill="#ffb703"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<!-- Squiggle middle left -->
|
||||||
|
<div class="absolute top-1/2 -mt-10 left-6 w-5 h-12 hidden sm:block">
|
||||||
|
<svg viewBox="0 0 20 50" fill="none" stroke="#a78bfa" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M10,5 C18,10 2,20 10,25 C18,30 2,40 10,45" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<!-- Blue dot top right (left col) -->
|
||||||
|
<div class="absolute top-20 right-12 w-4 h-4 hidden sm:block">
|
||||||
|
<svg viewBox="0 0 24 24" fill="#3b82f6" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M12 0L15.5 8.5L24 12L15.5 15.5L12 24L8.5 15.5L0 12L8.5 8.5L12 0Z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Logo -->
|
||||||
|
<div class="flex justify-start mb-10 relative z-10">
|
||||||
|
<img src="{{ asset('images/logo.png') }}" alt="GMO-Z.com RUNSYSTEM" class="h-6 sm:h-8 w-auto object-contain">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="text-center mb-8 relative z-10">
|
||||||
|
<h1 class="text-3xl font-bold text-[#1e293b] mb-3 flex items-center justify-center gap-2">
|
||||||
|
Welcome back! <span class="text-2xl origin-bottom-right hover:animate-bounce">👋</span>
|
||||||
|
</h1>
|
||||||
|
<p class="text-[13px] text-gray-500 font-medium max-w-[320px] mx-auto leading-relaxed">
|
||||||
|
Đăng nhập để tiếp tục lan tỏa những lời cảm ơn và tạo nên môi trường làm việc tích cực.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Form -->
|
||||||
|
<div class="w-full max-w-[380px] mx-auto flex-1 relative z-10">
|
||||||
|
<form action="{{ route('login') }}" method="POST" class="space-y-5">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="min-h-[40px] flex items-center justify-center transition-all duration-300" aria-live="polite">
|
||||||
|
@if($errors->any())
|
||||||
|
<div id="login-errors" class="w-full bg-red-50 text-red-600 text-[13px] font-semibold p-2.5 rounded-lg border border-red-200 flex items-start gap-2" role="alert">
|
||||||
|
<svg class="h-4 w-4 shrink-0 mt-0.5 text-red-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /></svg>
|
||||||
|
<span>{{ $errors->first() }}</span>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Email Field -->
|
||||||
|
<div class="space-y-1.5">
|
||||||
|
<label for="mail" class="block text-[13px] font-bold text-gray-700">Email</label>
|
||||||
|
<div class="relative">
|
||||||
|
<span class="absolute left-3.5 top-1/2 -translate-y-1/2 text-gray-400">
|
||||||
|
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" /></svg>
|
||||||
|
</span>
|
||||||
|
<input type="email" name="mail" id="mail" placeholder="Nhập email của bạn" required value="{{ old('mail') }}" autocomplete="email" class="w-full h-[46px] pl-[42px] pr-4 bg-white border border-gray-200 rounded-lg text-sm text-gray-800 focus:border-[#2563eb] focus:ring-1 focus:ring-[#2563eb] outline-none transition-all shadow-sm placeholder:text-gray-400 @error('mail') border-red-500 @enderror" @error('mail') aria-invalid="true" aria-describedby="login-errors" @enderror />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Password Field -->
|
||||||
|
<div class="space-y-1.5">
|
||||||
|
<label for="password" class="block text-[13px] font-bold text-gray-700">Mật khẩu</label>
|
||||||
|
<div class="relative">
|
||||||
|
<span class="absolute left-3.5 top-1/2 -translate-y-1/2 text-gray-400">
|
||||||
|
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0V10.5m-2.812 10.5h14.625c.621 0 1.125-.504 1.125-1.125V11.25c0-.621-.504-1.125-1.125-1.125H3.75c-.621 0-1.125.504-1.125 1.125v7.875c0 .621.504 1.125 1.125 1.125z" /></svg>
|
||||||
|
</span>
|
||||||
|
<input type="password" name="password" id="password" placeholder="Nhập mật khẩu" required autocomplete="current-password" class="w-full h-[46px] pl-[42px] pr-12 bg-white border border-gray-200 rounded-lg text-sm text-gray-800 focus:border-[#2563eb] focus:ring-1 focus:ring-[#2563eb] outline-none transition-all shadow-sm placeholder:text-gray-400 @error('password') border-red-500 @enderror" @error('password') aria-invalid="true" aria-describedby="login-errors" @enderror />
|
||||||
|
<button type="button" onclick="togglePasswordVisibility('password', this)" class="absolute right-3.5 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 focus:outline-none" aria-label="Show password">
|
||||||
|
<!-- Eye Closed (Default) -->
|
||||||
|
<svg class="w-5 h-5 eye-icon-closed" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88" /></svg>
|
||||||
|
<!-- Eye Open -->
|
||||||
|
<svg class="w-5 h-5 eye-icon-open hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pt-4">
|
||||||
|
<button type="submit" class="w-full h-[46px] bg-[#1d4ed8] hover:bg-[#1e40af] text-white font-bold rounded-lg shadow-md hover:shadow-lg transition-all duration-200 text-[14px]">
|
||||||
|
Đăng nhập
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center mt-auto pt-8 relative z-10">
|
||||||
|
<span class="text-[11px] font-medium text-gray-400">© 2024 GMO-Z.com RUNSYSTEM. All rights reserved.</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- RIGHT COLUMN: Illustration Side -->
|
||||||
|
<div class="hidden lg:flex w-[50%] bg-[#f8faff] relative flex-col items-center justify-center p-12 overflow-hidden border-l border-gray-100">
|
||||||
|
|
||||||
|
<!-- Right Column Decorations -->
|
||||||
|
<div class="absolute inset-0 pointer-events-none">
|
||||||
|
<!-- Top left blue strokes -->
|
||||||
|
<svg class="absolute top-16 left-16 w-10 h-10 text-blue-500" viewBox="0 0 50 50" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round">
|
||||||
|
<path d="M10,20 L25,10" />
|
||||||
|
<path d="M15,35 L30,25" />
|
||||||
|
<path d="M30,40 L40,30" />
|
||||||
|
</svg>
|
||||||
|
<!-- Heart icon top right -->
|
||||||
|
<div class="absolute top-20 right-20 w-12 h-12 flex items-center justify-center">
|
||||||
|
<svg viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M50 88C50 88 15 62 15 35C15 20 28 10 40 15C45 17 50 24 50 24C50 24 55 17 60 15C72 10 85 20 85 35C85 62 50 88 50 88Z" stroke="#3b82f6" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<!-- Sparkle top right -->
|
||||||
|
<svg class="absolute top-12 right-12 w-6 h-6 text-purple-400" viewBox="0 0 24 24" fill="none">
|
||||||
|
<path d="M12 0L14.59 9.41L24 12L14.59 14.59L12 24L9.41 14.59L0 12L9.41 9.41L12 0Z" fill="currentColor"/>
|
||||||
|
</svg>
|
||||||
|
<!-- Thumbs up bottom right -->
|
||||||
|
<div class="absolute bottom-32 right-16 w-14 h-14 bg-white rounded-lg flex items-center justify-center shadow-lg transform rotate-12 z-20">
|
||||||
|
<span class="text-3xl">👍</span>
|
||||||
|
</div>
|
||||||
|
<!-- Paper plane -->
|
||||||
|
<div class="absolute top-1/3 left-10 w-10 h-10 transform -rotate-12 z-20">
|
||||||
|
<svg viewBox="0 0 24 24" fill="#3b82f6" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M2 12L22 2L15 22L11 15L2 12Z"/>
|
||||||
|
</svg>
|
||||||
|
<!-- Dashed trail -->
|
||||||
|
<svg class="absolute top-full left-0 w-24 h-24 text-gray-300" style="transform: translate(-90%, -30%);" viewBox="0 0 100 100" fill="none" stroke="currentColor" stroke-width="2" stroke-dasharray="4 4">
|
||||||
|
<path d="M100,0 Q50,50 0,100" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<!-- Purple squiggle bottom right -->
|
||||||
|
<svg class="absolute bottom-24 right-10 w-8 h-16 text-purple-400" viewBox="0 0 30 60" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M20,10 C5,20 25,30 10,40 C25,50 5,60 20,70" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Header Content -->
|
||||||
|
<div class="text-center mb-6 relative z-10 pt-4">
|
||||||
|
<h2 class="text-[40px] font-extrabold text-[#1e293b] flex items-center justify-center gap-3 mb-2">
|
||||||
|
Thanks <span class="text-[#ff7eb3] font-bold text-[48px] leading-none tracking-wider" style="font-family: 'Caveat', cursive;">card</span>
|
||||||
|
<svg class="w-8 h-8 text-[#3b82f6] transform -rotate-12" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
|
||||||
|
</svg>
|
||||||
|
</h2>
|
||||||
|
<p class="text-gray-700 font-medium text-[14px] max-w-[300px] mx-auto leading-relaxed">
|
||||||
|
Gửi lời cảm ơn chân thành đến đồng nghiệp và cùng nhau xây dựng văn hóa tích cực!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Illustration (Image) -->
|
||||||
|
<div class="relative w-full max-w-[460px] flex-1 flex items-end justify-center z-10 mt-4">
|
||||||
|
<img src="{{ asset('images/thanks_card_illustration.png') }}" alt="Thanks card illustration" class="w-full h-auto object-contain drop-shadow-xl hover:scale-[1.05] transition-transform duration-500 rounded-3xl" style="mix-blend-mode: multiply;">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,6 +1,173 @@
|
|||||||
@extends('layouts.app')
|
@extends('layouts.app')
|
||||||
@section('title', 'My Page')
|
|
||||||
|
@section('title', 'Trang chủ')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<x-user-page mode="self" :user="$user" :administrations="$administrations" :selectedMonth="$selectedMonth" />
|
<div class="max-w-[1280px] mx-auto w-full pb-10 px-2 lg:px-8">
|
||||||
|
|
||||||
|
<!-- Welcome Section -->
|
||||||
|
<div class="mb-6 pl-1">
|
||||||
|
<h1 class="text-[28px] font-extrabold text-[#1a2b49] flex items-center gap-2 mb-1.5 tracking-tight">
|
||||||
|
Hey {{ Auth::check() ? (Auth::user()->name ?? 'Minh Anh') : 'Minh Anh' }}! <span class="text-2xl animate-bounce">👋</span>
|
||||||
|
</h1>
|
||||||
|
<p class="text-gray-500 font-medium text-[14px]">Cảm ơn bạn đã góp phần tạo nên một tập thể tuyệt vời!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Row 1: Hero -->
|
||||||
|
<div class="mb-6">
|
||||||
|
<x-hero-banner />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Row 2: Statistics -->
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
|
||||||
|
<x-stat-card
|
||||||
|
title="Thanks đã nhận"
|
||||||
|
value="128"
|
||||||
|
iconBgClass="bg-purple-50"
|
||||||
|
iconColorClass="text-purple-500">
|
||||||
|
<svg class="w-[26px] h-[26px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
|
||||||
|
</svg>
|
||||||
|
</x-stat-card>
|
||||||
|
|
||||||
|
<x-stat-card
|
||||||
|
title="Thanks đã gửi"
|
||||||
|
value="82"
|
||||||
|
iconBgClass="bg-blue-50"
|
||||||
|
iconColorClass="text-blue-500">
|
||||||
|
<svg class="w-[26px] h-[26px] transform -rotate-45" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
|
||||||
|
</svg>
|
||||||
|
</x-stat-card>
|
||||||
|
|
||||||
|
|
||||||
|
<x-stat-card
|
||||||
|
title="Thứ hạng"
|
||||||
|
value="#5"
|
||||||
|
iconBgClass="bg-green-50"
|
||||||
|
iconColorClass="text-green-500">
|
||||||
|
<svg class="w-[26px] h-[26px]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||||
|
</svg>
|
||||||
|
</x-stat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Row 3: Thanks Grid & Ranking -->
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||||
|
<!-- Recent Thanks (Left 2/3) -->
|
||||||
|
<div class="col-span-1 lg:col-span-2 flex flex-col">
|
||||||
|
<div class="flex items-center justify-between mb-4 pl-1 pr-1">
|
||||||
|
<h3 class="text-[17px] font-extrabold text-[#1a2b49]">Thanks gần đây</h3>
|
||||||
|
<a href="{{ route('user.received') }}" class="text-[13px] font-bold text-[#3462f7] hover:text-blue-800">Xem tất cả</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 flex-1">
|
||||||
|
<x-thank-card
|
||||||
|
title="GREAT JOB!"
|
||||||
|
message="Cảm ơn bạn đã luôn nhiệt tình giúp đỡ và đồng hành cùng mọi người. Chúc bạn một ngày làm việc thật vui vẻ và tràn đầy năng lượng!"
|
||||||
|
:isLiked="false"
|
||||||
|
bgClass="bg-[#fff9e6]"
|
||||||
|
titleColorClass="text-[#f59e0b]"
|
||||||
|
textColorClass="text-[#d97706]"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<x-thank-card
|
||||||
|
title="YOU ROCK!"
|
||||||
|
message="Sự cống hiến và tinh thần làm việc trách nhiệm của bạn luôn là nguồn cảm hứng lớn. Cảm ơn vì những nỗ lực không ngừng nghỉ của bạn!"
|
||||||
|
:isLiked="true"
|
||||||
|
bgClass="bg-[#faf5ff]"
|
||||||
|
titleColorClass="text-[#a855f7]"
|
||||||
|
textColorClass="text-[#7e22ce]"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<x-thank-card
|
||||||
|
title="THANK YOU!"
|
||||||
|
message="Rất vui và may mắn khi được làm việc cùng một người đồng nghiệp tuyệt vời. Cảm ơn bạn vì tất cả những đóng góp tích cực cho tập thể!"
|
||||||
|
:isLiked="false"
|
||||||
|
bgClass="bg-[#f0f9ff]"
|
||||||
|
titleColorClass="text-[#0ea5e9]"
|
||||||
|
textColorClass="text-[#0369a1]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6 w-full">
|
||||||
|
<x-info-card />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Ranking and Tip (Right 1/3) -->
|
||||||
|
<div class="col-span-1 flex flex-col">
|
||||||
|
<div class="flex items-center justify-between mb-3 pl-1 pr-1">
|
||||||
|
<h3 class="text-[17px] font-extrabold text-[#1a2b49]">Bảng xếp hạng</h3>
|
||||||
|
<a href="{{ route('user.ranking') }}" class="text-[13px] font-bold text-[#3462f7] hover:text-blue-800">Xem tất cả</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tabs Toggle -->
|
||||||
|
<div class="inline-flex bg-[#F5F7FB] rounded-xl p-1 mb-4 w-fit">
|
||||||
|
<button id="tab-received" onclick="switchRankingTab('received')" class="flex items-center justify-center gap-2 w-[135px] py-2 rounded-[10px] transition-all bg-white shadow-[0_2px_4px_rgba(0,0,0,0.04)] text-[#3462f7] font-bold text-[14px]">
|
||||||
|
<svg class="w-[18px] h-[18px]" fill="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path d="M17.5 4h-11c-1.38 0-2.5 1.12-2.5 2.5V8c0 2.21 1.79 4 4 4h.34c1.17 2.19 3.52 3.56 6.16 3.56s4.99-1.37 6.16-3.56h.34c2.21 0 4-1.79 4-4v-1.5c0-1.38-1.12-2.5-2.5-2.5zm-11 6c-.55 0-1-.45-1-1V6.5c0-.28.22-.5.5-.5h2v4H6.5zm11 0h-2v-4h2c.28 0 .5.22.5.5V9c0 .55-.45 1-1 1zM11 16h2v4h-2v-4zm-2 4h6v2H9v-2z"/>
|
||||||
|
<path fill="#ffffff" d="M12 11.5L10 7h4z"/>
|
||||||
|
</svg>
|
||||||
|
TOP Nhận
|
||||||
|
</button>
|
||||||
|
<button id="tab-sent" onclick="switchRankingTab('sent')" class="flex items-center justify-center gap-2 w-[135px] py-2 rounded-[10px] transition-all text-[#64748b] hover:text-gray-800 font-bold text-[14px]">
|
||||||
|
<svg class="w-[18px] h-[18px]" fill="none" stroke="currentColor" stroke-width="2.2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M22 2L11 13"></path>
|
||||||
|
<path d="M22 2L15 22L11 13L2 9L22 2Z"></path>
|
||||||
|
</svg>
|
||||||
|
TOP Gửi
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tab Content: Received -->
|
||||||
|
<div id="ranking-received" class="bg-white rounded-2xl p-4 border border-gray-100 shadow-[0_2px_10px_-4px_rgba(0,0,0,0.05)] flex-1 flex flex-col mb-4">
|
||||||
|
<x-ranking-item rank="1" name="Lê Quỳnh Chi" team="Marketing Team" avatar="https://api.dicebear.com/7.x/notionists/svg?seed=Chi&backgroundColor=fef3c7" score="95" unit="thẻ" />
|
||||||
|
<x-ranking-item rank="2" name="Trần Hoàng Nam" team="Dev Team" avatar="https://api.dicebear.com/7.x/notionists/svg?seed=Nam&backgroundColor=e2e8f0" score="82" unit="thẻ" />
|
||||||
|
<x-ranking-item rank="3" name="Phạm Đức Huy" team="Product Team" avatar="https://api.dicebear.com/7.x/notionists/svg?seed=Huy&backgroundColor=e2e8f0" score="67" unit="thẻ" />
|
||||||
|
|
||||||
|
<div class="my-3 border-t border-dashed border-gray-100 mx-2"></div>
|
||||||
|
|
||||||
|
<x-ranking-item rank="5" name="{{ Auth::check() ? (Auth::user()->name ?? 'Nguyễn Minh Anh') : 'Nguyễn Minh Anh' }}" team="Product Team" avatar="https://api.dicebear.com/7.x/notionists/svg?seed={{ Auth::id() ?? 'MinhAnh' }}&backgroundColor=bfdbfe" score="45" unit="thẻ" :isCurrent="true" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tab Content: Sent -->
|
||||||
|
<div id="ranking-sent" class="bg-white rounded-2xl p-4 border border-gray-100 shadow-[0_2px_10px_-4px_rgba(0,0,0,0.05)] flex-1 flex flex-col mb-4 hidden">
|
||||||
|
<x-ranking-item rank="1" name="Nguyễn Văn Lâm" team="HR Team" avatar="https://api.dicebear.com/7.x/notionists/svg?seed=Lam&backgroundColor=fef3c7" score="88" unit="thẻ" />
|
||||||
|
<x-ranking-item rank="2" name="Phạm Thu Thủy" team="Admin Team" avatar="https://api.dicebear.com/7.x/notionists/svg?seed=Thuy&backgroundColor=e2e8f0" score="75" unit="thẻ" />
|
||||||
|
<x-ranking-item rank="3" name="Lê Quỳnh Chi" team="Marketing Team" avatar="https://api.dicebear.com/7.x/notionists/svg?seed=Chi&backgroundColor=e2e8f0" score="64" unit="thẻ" />
|
||||||
|
|
||||||
|
<div class="my-3 border-t border-dashed border-gray-100 mx-2"></div>
|
||||||
|
|
||||||
|
<x-ranking-item rank="12" name="{{ Auth::check() ? (Auth::user()->name ?? 'Nguyễn Minh Anh') : 'Nguyễn Minh Anh' }}" team="Product Team" avatar="https://api.dicebear.com/7.x/notionists/svg?seed={{ Auth::id() ?? 'MinhAnh' }}&backgroundColor=bfdbfe" score="18" unit="thẻ" :isCurrent="true" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script>
|
||||||
|
function switchRankingTab(tab) {
|
||||||
|
const receivedTab = document.getElementById('tab-received');
|
||||||
|
const sentTab = document.getElementById('tab-sent');
|
||||||
|
const receivedContent = document.getElementById('ranking-received');
|
||||||
|
const sentContent = document.getElementById('ranking-sent');
|
||||||
|
|
||||||
|
const activeClass = 'flex items-center justify-center gap-2 w-[135px] py-2 rounded-[10px] transition-all bg-white shadow-[0_2px_4px_rgba(0,0,0,0.04)] text-[#3462f7] font-bold text-[14px]';
|
||||||
|
const inactiveClass = 'flex items-center justify-center gap-2 w-[135px] py-2 rounded-[10px] transition-all text-[#64748b] hover:text-gray-800 font-bold text-[14px]';
|
||||||
|
|
||||||
|
if (tab === 'received') {
|
||||||
|
receivedTab.className = activeClass;
|
||||||
|
sentTab.className = inactiveClass;
|
||||||
|
receivedContent.classList.remove('hidden');
|
||||||
|
sentContent.classList.add('hidden');
|
||||||
|
} else {
|
||||||
|
sentTab.className = activeClass;
|
||||||
|
receivedTab.className = inactiveClass;
|
||||||
|
sentContent.classList.remove('hidden');
|
||||||
|
receivedContent.classList.add('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use App\Http\Controllers\Admin\AdminController;
|
||||||
|
|
||||||
|
Route::middleware(['auth', 'force_change_password', 'admin'])->prefix('admin')->name('admin.')->group(function () {
|
||||||
|
Route::get('/', [AdminController::class, 'index'])->name('dashboard');
|
||||||
|
Route::get('/users', [AdminController::class, 'index'])->name('users.index');
|
||||||
|
|
||||||
|
Route::get('/users/create', [AdminController::class, 'create'])->name('users.create');
|
||||||
|
Route::post('/users', [AdminController::class, 'store'])->name('users.store');
|
||||||
|
Route::get('/users/{msnv}/edit', [AdminController::class, 'edit'])->name('users.edit');
|
||||||
|
Route::put('/users/{msnv}', [AdminController::class, 'update'])->name('users.update');
|
||||||
|
Route::delete('/users/{msnv}', [AdminController::class, 'destroy'])->name('users.destroy');
|
||||||
|
|
||||||
|
Route::post('/reset-cards', [AdminController::class, 'resetCards'])->name('reset_cards');
|
||||||
|
});
|
||||||
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use App\Http\Controllers\AuthController;
|
use App\Http\Controllers\AuthController;
|
||||||
use App\Http\Controllers\AdminController;
|
use App\Http\Controllers\User\UserController;
|
||||||
use App\Http\Controllers\UserController;
|
|
||||||
|
|
||||||
Route::get('/', function () {
|
Route::get('/', function () {
|
||||||
return redirect()->route('login');
|
return redirect()->route('login');
|
||||||
@@ -40,22 +39,18 @@ Route::middleware('auth')->group(function () {
|
|||||||
|
|
||||||
Route::middleware('force_change_password')->group(function () {
|
Route::middleware('force_change_password')->group(function () {
|
||||||
|
|
||||||
Route::middleware('admin')->prefix('admin')->name('admin.')->group(function () {
|
|
||||||
Route::get('/', [AdminController::class, 'index'])->name('dashboard');
|
|
||||||
Route::get('/users', [AdminController::class, 'index'])->name('users.index');
|
|
||||||
|
|
||||||
Route::get('/users/create', [AdminController::class, 'create'])->name('users.create');
|
|
||||||
Route::post('/users', [AdminController::class, 'store'])->name('users.store');
|
|
||||||
Route::get('/users/{msnv}/edit', [AdminController::class, 'edit'])->name('users.edit');
|
|
||||||
Route::put('/users/{msnv}', [AdminController::class, 'update'])->name('users.update');
|
|
||||||
Route::delete('/users/{msnv}', [AdminController::class, 'destroy'])->name('users.destroy');
|
|
||||||
|
|
||||||
Route::post('/reset-cards', [AdminController::class, 'resetCards'])->name('reset_cards');
|
|
||||||
});
|
|
||||||
|
|
||||||
Route::middleware('member')->group(function () {
|
Route::middleware('member')->group(function () {
|
||||||
Route::get('/my-page', [UserController::class, 'index'])->name('user.dashboard');
|
Route::get('/my-page', [UserController::class, 'index'])->name('user.dashboard');
|
||||||
|
|
||||||
|
// Coming soon routes for new tabs
|
||||||
|
Route::view('/received-cards', 'coming-soon')->name('user.received');
|
||||||
|
Route::view('/sent-cards', 'coming-soon')->name('user.sent');
|
||||||
|
Route::view('/ranking', 'coming-soon')->name('user.ranking');
|
||||||
|
Route::view('/gallery', 'coming-soon')->name('user.gallery');
|
||||||
|
Route::view('/stats', 'coming-soon')->name('user.stats');
|
||||||
|
|
||||||
Route::get('/send-thankcards', [UserController::class, 'sendThankcards'])->name('user.send');
|
Route::get('/send-thankcards', [UserController::class, 'sendThankcards'])->name('user.send');
|
||||||
Route::post('/send-thankcards', [UserController::class, 'storeThankcards'])->name('user.store_send');
|
Route::post('/send-thankcards', [UserController::class, 'storeThankcards'])->name('user.store_send');
|
||||||
});
|
});
|
||||||
|
|||||||