sidebar component and login page done

This commit is contained in:
armiejean 2025-04-15 00:12:11 +08:00
parent 717e6eb700
commit 0fa9d76b89
51 changed files with 2910 additions and 181 deletions

100
app/Services/ApiService.php Normal file
View File

@ -0,0 +1,100 @@
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Log;
class ApiService
{
protected $baseUrl;
public function __construct()
{
$this->baseUrl = config('app.api_base_url');
}
public function fetchData($url, $token = null)
{
try {
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . ($token ?: Session::get('token', '')),
])->get($this->baseUrl . $url);
if ($response->successful()) {
return $response->json();
} else {
$this->handleError($response);
return null;
}
} catch (\Exception $e) {
Log::error('API Fetch Error: ' . $e->getMessage());
Session::flash('error', 'Failed to fetch data: ' . $e->getMessage());
return null;
}
}
public function logout($token = null)
{
try {
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . ($token ?: Session::get('token', '')),
])->get($this->baseUrl . '/logout');
if ($response->successful()) {
Session::forget('token');
Session::flash('success', 'Logged out successfully.');
return true;
} else {
$this->handleError($response);
return false;
}
} catch (\Exception $e) {
Log::error('Logout Error: ' . $e->getMessage());
Session::flash('error', 'Logout failed: ' . $e->getMessage());
return false;
}
}
public function handleError($response)
{
$status = $response->status();
if ($status === 401) {
Session::forget('token');
throw new \Exception('Session expired. Please login again.');
} elseif ($status === 404) {
throw new \Exception('API resource not found.');
} else {
throw new \Exception('API error: ' . ($response->body() ?: 'Unknown error'));
}
}
public function get($url, $params = [])
{
$token = $this->cookieService->getCookie()['token'] ?? null;
$this->defaultHeaders['Authorization'] = 'Bearer ' . $token;
return $this->makeRequest('get', $url, $params);
}
public function post($url, $params = [])
{
return $this->makeRequest('post', $url, $params);
}
public function put($url, $params = [])
{
return $this->makeRequest('put', $url, $params);
}
public function delete($url, $params = [])
{
return $this->makeRequest('delete', $url, ['params' => $params]);
}
public function postMultipart($url, $data)
{
return $this->makeRequest('postMultipart', $url, $data);
}
}

View File

@ -0,0 +1,89 @@
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Log;
use App\Livewire\ErrorHandler;
class BaseApiService
{
protected $baseUrl;
protected $defaultHeaders = [];
public function __construct(string $baseUrl)
{
$this->baseUrl = $baseUrl;
}
protected function makeRequest($method, $url, $params = [], $headers = [])
{
try {
$fullHeaders = array_merge($this->defaultHeaders, $headers, [
'Authorization' => 'Bearer ' . Session::get('token', ''),
]);
$response = Http::withHeaders($fullHeaders)->{$method}($this->baseUrl . $url, $params);
if ($response->successful()) {
return $response->json();
} else {
$this->handleError($response);
return null;
}
} catch (\Exception $e) {
Log::error('API Request Error: ' . $e->getMessage());
Session::flash('error', 'API request failed: ' . $e->getMessage());
return null;
}
}
protected function handleError($response)
{
$status = $response->status();
if ($status === 401) {
Session::forget('token');
throw new \Exception('Session expired. Please login again.');
} elseif ($status === 422) {
throw new \Exception('Validation error: ' . ($response->body() ?: 'Unknown validation error'));
} elseif ($status === 404) {
throw new \Exception('API resource not found.');
} else {
throw new \Exception('API error: ' . ($response->body() ?: 'Unknown error'));
}
}
public function postMultipart($url, $data)
{
try {
$headers = array_merge($this->defaultHeaders, [
'Authorization' => 'Bearer ' . Session::get('token', ''),
'Content-Type' => 'multipart/form-data',
]);
$response = Http::withHeaders($headers)->asMultipart();
foreach ($data as $key => $value) {
if ($value instanceof \Illuminate\Http\UploadedFile) {
$response = $response->attach($key, $value->get(), $value->getClientOriginalName());
} else {
$response = $response->attach($key, $value);
}
}
$response = $response->post($this->baseUrl . $url);
if ($response->successful()) {
return $response->json();
} else {
$this->handleError($response);
return null;
}
} catch (\Exception $e) {
Log::error('Multipart API Request Error: ' . $e->getMessage());
throw $e;
}
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace App\Services;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Log;
class CookieService
{
const COOKIE_NAME = 'FRONT_END_REST';
const PUBLIC_KEY = 'PUBLIC_00001';
const TIME_OUT_HOURS = 1; // 60 minutes
public function setCookie(array $params, string $name = self::COOKIE_NAME): bool
{
try {
if (!is_array($params)) {
throw new \TypeError('setCookie params should be an array.', 'CookieService.php', 20);
}
$expiration = now()->addHours(self::TIME_OUT_HOURS);
$encryptedValue = Crypt::encryptString(json_encode($params));
Cookie::queue($name, $encryptedValue, $expiration->diffInMinutes(), '/', null, false, true);
return true;
} catch (\Exception $e) {
Log::error('Cookie Set Error: ' . $e->getMessage());
return false;
}
}
public function getCookie(string $name = self::COOKIE_NAME)
{
$cookie = Cookie::get($name);
if (!$cookie) {
return null;
}
try {
return json_decode(Crypt::decryptString($cookie), true);
} catch (\Exception $e) {
Log::error('Cookie Get Error: ' . $e->getMessage());
return null;
}
}
public function removeCookie(string $name = self::COOKIE_NAME): bool
{
Cookie::queue(Cookie::forget($name));
return true;
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace App\Services;
use Illuminate\Support\Facades\Session;
class EncryptionService
{
const ALGORITHM = 'aes-256-ctr';
private $password;
public function __construct()
{
$this->password = $this->getPasswordFromCookie();
}
private function getPasswordFromCookie()
{
$cookieService = app(CookieService::class);
$cookie = $cookieService->getCookie(process.env.REACT_APP_TOKEN ?? 'token');
return $cookie['token'] ?? 'default_password'; // Fallback if token not found
}
public function encrypt(string $text): string
{
$iv = random_bytes(16); // Initialization vector
$encrypted = openssl_encrypt($text, self::ALGORITHM, $this->password, 0, $iv);
return base64_encode($iv . $encrypted); // Combine IV and encrypted data
}
public function decrypt(string $text): string|bool
{
$data = base64_decode($text);
$iv = substr($data, 0, 16);
$encrypted = substr($data, 16);
$decrypted = openssl_decrypt($encrypted, self::ALGORITHM, $this->password, 0, $iv);
if ($decrypted === false) {
return false;
}
// Check if the result is hexadecimal (simulating your JS check)
if (preg_match('/^[0-9a-fA-F]+$/', $decrypted)) {
return $decrypted;
}
return false;
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Services;
class NotificationApiService extends BaseApiService
{
public function __construct()
{
parent::__construct(config('app.notif_api_base_url'));
}
public function getNotification($url, $params = [])
{
return $this->makeRequest('get', $url, $params);
}
public function postNotification($url, $params = [])
{
return $this->makeRequest('post', $url, $params);
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace App\Services;
class StationApiService extends BaseApiService
{
public function __construct()
{
parent::__construct(config('app.station_api_base_url'));
$this->defaultHeaders = array_merge($this->defaultHeaders, [
'X-Requested-With' => 'station-locator-api',
]);
}
public function getBranch($url, $params = [])
{
return $this->makeRequest('get', $url, $params);
}
public function postBranch($url, $params = [])
{
return $this->makeRequest('post', $url, $params);
}
public function putBranch($url, $params = [])
{
return $this->makeRequest('put', $url, $params);
}
public function deleteBranch($url, $params = [])
{
return $this->makeRequest('delete', $url, ['params' => $params]);
}
public function postFuel($url, $params = [])
{
return $this->makeRequest('post', $url, $params);
}
public function putFuel($url, $params = [])
{
return $this->makeRequest('put', $url, $params);
}
public function getFuels($url, $params = [])
{
return $this->makeRequest('get', $url, $params);
}
public function getCsv($url, $params = [])
{
return Http::withHeaders(array_merge($this->defaultHeaders, [
'Authorization' => 'Bearer ' . Session::get('token', ''),
]))->get($this->baseUrl . $url, $params)->body(); // Return raw text for CSV
}
}

0
bootstrap/cache/.gitignore vendored Normal file → Executable file
View File

View File

@ -45,11 +45,11 @@ return [
'mysql' => [
'driver' => 'mysql',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'host' => env('DB_HOST', 'db_mysql'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'database' => env('DB_DATABASE', 'laravel-cms'),
'username' => env('DB_USERNAME', 'laravel_user'),
'password' => env('DB_PASSWORD', 'password'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),

160
config/livewire.php Normal file
View File

@ -0,0 +1,160 @@
<?php
return [
/*
|---------------------------------------------------------------------------
| Class Namespace
|---------------------------------------------------------------------------
|
| This value sets the root class namespace for Livewire component classes in
| your application. This value will change where component auto-discovery
| finds components. It's also referenced by the file creation commands.
|
*/
'class_namespace' => 'App\\Livewire',
/*
|---------------------------------------------------------------------------
| View Path
|---------------------------------------------------------------------------
|
| This value is used to specify where Livewire component Blade templates are
| stored when running file creation commands like `artisan make:livewire`.
| It is also used if you choose to omit a component's render() method.
|
*/
'view_path' => resource_path('views/livewire'),
/*
|---------------------------------------------------------------------------
| Layout
|---------------------------------------------------------------------------
| The view that will be used as the layout when rendering a single component
| as an entire page via `Route::get('/post/create', CreatePost::class);`.
| In this case, the view returned by CreatePost will render into $slot.
|
*/
'layout' => 'components.layouts.app',
/*
|---------------------------------------------------------------------------
| Lazy Loading Placeholder
|---------------------------------------------------------------------------
| Livewire allows you to lazy load components that would otherwise slow down
| the initial page load. Every component can have a custom placeholder or
| you can define the default placeholder view for all components below.
|
*/
'lazy_placeholder' => null,
/*
|---------------------------------------------------------------------------
| Temporary File Uploads
|---------------------------------------------------------------------------
|
| Livewire handles file uploads by storing uploads in a temporary directory
| before the file is stored permanently. All file uploads are directed to
| a global endpoint for temporary storage. You may configure this below:
|
*/
'temporary_file_upload' => [
'disk' => null, // Example: 'local', 's3' | Default: 'default'
'rules' => null, // Example: ['file', 'mimes:png,jpg'] | Default: ['required', 'file', 'max:12288'] (12MB)
'directory' => null, // Example: 'tmp' | Default: 'livewire-tmp'
'middleware' => null, // Example: 'throttle:5,1' | Default: 'throttle:60,1'
'preview_mimes' => [ // Supported file types for temporary pre-signed file URLs...
'png', 'gif', 'bmp', 'svg', 'wav', 'mp4',
'mov', 'avi', 'wmv', 'mp3', 'm4a',
'jpg', 'jpeg', 'mpga', 'webp', 'wma',
],
'max_upload_time' => 5, // Max duration (in minutes) before an upload is invalidated...
'cleanup' => true, // Should cleanup temporary uploads older than 24 hrs...
],
/*
|---------------------------------------------------------------------------
| Render On Redirect
|---------------------------------------------------------------------------
|
| This value determines if Livewire will run a component's `render()` method
| after a redirect has been triggered using something like `redirect(...)`
| Setting this to true will render the view once more before redirecting
|
*/
'render_on_redirect' => false,
/*
|---------------------------------------------------------------------------
| Eloquent Model Binding
|---------------------------------------------------------------------------
|
| Previous versions of Livewire supported binding directly to eloquent model
| properties using wire:model by default. However, this behavior has been
| deemed too "magical" and has therefore been put under a feature flag.
|
*/
'legacy_model_binding' => false,
/*
|---------------------------------------------------------------------------
| Auto-inject Frontend Assets
|---------------------------------------------------------------------------
|
| By default, Livewire automatically injects its JavaScript and CSS into the
| <head> and <body> of pages containing Livewire components. By disabling
| this behavior, you need to use @livewireStyles and @livewireScripts.
|
*/
'inject_assets' => true,
/*
|---------------------------------------------------------------------------
| Navigate (SPA mode)
|---------------------------------------------------------------------------
|
| By adding `wire:navigate` to links in your Livewire application, Livewire
| will prevent the default link handling and instead request those pages
| via AJAX, creating an SPA-like effect. Configure this behavior here.
|
*/
'navigate' => [
'show_progress_bar' => true,
'progress_bar_color' => '#2299dd',
],
/*
|---------------------------------------------------------------------------
| HTML Morph Markers
|---------------------------------------------------------------------------
|
| Livewire intelligently "morphs" existing HTML into the newly rendered HTML
| after each update. To make this process more reliable, Livewire injects
| "markers" into the rendered Blade surrounding @if, @class & @foreach.
|
*/
'inject_morph_markers' => true,
/*
|---------------------------------------------------------------------------
| Pagination Theme
|---------------------------------------------------------------------------
|
| When enabling Livewire's pagination feature by using the `WithPagination`
| trait, Livewire will use Tailwind templates to render pagination views
| on the page. If you want Bootstrap CSS, you can specify: "bootstrap"
|
*/
'pagination_theme' => 'tailwind',
];

80
docker-compose.yml Normal file
View File

@ -0,0 +1,80 @@
version: '3.8'
services:
# Laravel App
app:
build:
context: ./docker/php
dockerfile: Dockerfile
container_name: laravel-app
restart: always
working_dir: /var/www
volumes:
- .:/var/www
depends_on:
db_mysql:
condition: service_healthy
command: >
/bin/sh -c '
mkdir -p /var/www/storage /var/www/bootstrap/cache &&
chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache &&
chmod -R 775 /var/www/storage /var/www/bootstrap/cache &&
composer install --no-dev --optimize-autoloader &&
php artisan migrate --force &&
php-fpm '
healthcheck:
test: ["CMD", "sh", "-c", "pgrep php-fpm"]
interval: 30s
timeout: 10s
retries: 10
networks:
- app_network
# MySQL
db_mysql:
image: mysql:8.0
container_name: db_mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: newpassword
MYSQL_DATABASE: laravel-cms
MYSQL_USER: laravel_user
MYSQL_PASSWORD: password
MYSQL_ALLOW_EMPTY_PASSWORD: "no"
volumes:
- mysql-data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-pnewpassword"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app_network
# Nginx
web:
image: nginx:1.26.3-alpine
container_name: web
restart: always
ports:
- "8000:80"
volumes:
- .:/var/www
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:rw
depends_on:
app:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 5
networks:
- app_network
volumes:
mysql-data:
networks:
app_network:
driver: bridge

28
docker/nginx/default.conf Normal file
View File

@ -0,0 +1,28 @@
server {
listen 80;
server_name localhost;
root /var/www/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi.conf;
fastcgi_pass app:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
}
# Deny access to .htaccess files
location ~ /\.ht {
deny all;
}
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
}

41
docker/php/Dockerfile Normal file
View File

@ -0,0 +1,41 @@
# Use PHP 8.2 Alpine (compatible with Laravel 11)
FROM php:8.2-fpm-alpine
# Install required dependencies
RUN apk add --no-cache \
oniguruma-dev \
libpng-dev \
libjpeg-turbo-dev \
libwebp-dev \
freetype-dev \
libzip-dev \
zip \
unzip \
openssl # Laravel requires OpenSSL for encryption
# Install required extensions
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
&& docker-php-ext-install gd pdo pdo_mysql bcmath mbstring zip
# Install Composer (using official Composer image)
COPY --from=composer:2.7 /usr/bin/composer /usr/bin/composer
# Set working directory
WORKDIR /var/www
# Copy Laravel application files BEFORE running composer install
COPY . /var/www/
# Ensure composer.json exists before running install
RUN if [ -f "composer.json" ]; then composer install --no-dev --optimize-autoloader; else echo "composer.json not found!"; fi
# Ensure required Laravel directories exist and set permissions
RUN mkdir -p /var/www/storage /var/www/bootstrap/cache && \
chown -R www-data:www-data /var/www && \
chmod -R 775 /var/www/storage /var/www/bootstrap/cache
# Expose PHP-FPM port
EXPOSE 9000
# Start PHP-FPM server
CMD ["php-fpm"]

31
package-lock.json generated
View File

@ -4,6 +4,10 @@
"requires": true,
"packages": {
"": {
"dependencies": {
"@popperjs/core": "^2.11.8",
"bootstrap": "^5.3.5"
},
"devDependencies": {
"autoprefixer": "^10.4.20",
"axios": "^1.7.4",
@ -536,6 +540,15 @@
"node": ">=14"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz",
@ -926,6 +939,24 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/bootstrap": {
"version": "5.3.5",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.5.tgz",
"integrity": "sha512-ct1CHKtiobRimyGzmsSldEtM03E8fcEX4Tb3dGXz1V8faRwM50+vfHwTzOxB3IlKO7m+9vTH3s/3C6T2EAPeTA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"peerDependencies": {
"@popperjs/core": "^2.11.8"
}
},
"node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",

View File

@ -13,5 +13,9 @@
"postcss": "^8.4.47",
"tailwindcss": "^3.4.13",
"vite": "^6.0.11"
},
"dependencies": {
"@popperjs/core": "^2.11.8",
"bootstrap": "^5.3.5"
}
}

7
public/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

755
public/css/custom.css Normal file
View File

@ -0,0 +1,755 @@
@import url('https://fonts.googleapis.com/css?family=Nova+Slim&display=swap');
body, html {
line-height: 1.8;
font-family: 'Roboto', sans-serif;
color: #555e58;
text-transform:capitalize;
text-rendering: optimizeLegibility !important;
-webkit-font-smoothing: antialiased !important;
font-weight: 400;
margin:0px;
padding:0px;
}
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4 {
font-weight: 400;
line-height: 1.5em;
}
p {
font-size: 15px;
margin: 12px 0 0;
line-height: 24px;
}
a{
color: #333;
font-weight: 400;
}
button:focus{
box-shadow:none;
outline:none;
border:none;
}
button{
cursor:pointer;
}
ul, ol {
padding: 0;
margin:0px;
list-style: none;
}
a,
a:hover,
a:focus {
color: #333;
text-decoration: none;
transition: all 0.3s;
}
/*=======================================================
material-icons copy & paste form site google material-icons
==================================================*/
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: url(https://example.com/MaterialIcons-Regular.eot); /* For IE6-8 */
src: local('Material Icons'),
local('MaterialIcons-Regular'),
url(https://example.com/MaterialIcons-Regular.woff2) format('woff2'),
url(https://example.com/MaterialIcons-Regular.woff) format('woff'),
url(https://example.com/MaterialIcons-Regular.ttf) format('truetype');
}
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px; /* Preferred icon size */
display: inline-block;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Safari and Chrome. */
text-rendering: optimizeLegibility;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;
/* Support for IE. */
font-feature-settings: 'liga';
}
/*=======================================================
material-icons copy & paste form site google material-icons
==================================================*/
.wrapper {
position: relative;
width:100%;
overflow:auto;
}
/* ---------------------------------------------------
SIDEBAR STYLE start
----------------------------------------------------- */
#sidebar {
position:fixed;
height:100vh!important;
top: 0;
bottom: 0;
left: 0;
z-index:11;
width: 260px;
overflow:auto;
transition:all 0.3s ;
background: #FFFFFF;
box-shadow: 0 10px 30px -12px rgb(0 0 0 / 42%), 0 4px 25px 0px rgb(0 0 0 / 12%), 0 8px 10px -5px rgb(0 0 0 / 20%);
}
#sidebar::-webkit-scrollbar{
width:5px;
border-radius:10px;
background-color:#eee;
display:none;
}
#sidebar::-webkit-scrollbar-thumbs{
width:5px;
border-radius:10px;
background-color:#333;
display:none;
}
#sidebar:hover::-webkit-scrollbar{
display:block;
}
#sidebar:hover::-webkit-scrollbar-thumbs{
display:block;
}
#sidebar .sidebar-header {
padding:20px;
background-color:#ffffff;
border-bottom:1px solid #eee;
}
.sidebar-header h3{
color:#333;
font-size:17px;
margin:0px;
text-transform:uppercase;
transition:all 0.5s ease;
font-weight:600;
}
.sidebar-header h3 img{
width:120px;
margin-right:10px;
}
#sidebar ul li{
padding:2px 7px;
}
#sidebar ul li.active>a{
color: #333;
background-color: rgba(200, 200, 200, 0.2);
}
#sidebar ul li a:hover{
color: #333;
background-color: rgba(200, 200, 200, 0.2);
}
.dropdown-toggle::after {
position: absolute;
right: 10px;
top: 23px;
}
#sidebar ul li.drodown{
position:sticky;
}
#sidebar ul.components {
padding: 20px 0;
}
#sidebar ul li a {
padding: 10px;
line-height: 30px;
border-radius:5px;
font-size: 15px;
position:relative;
font-weight: 400;
display: block;
}
#sidebar ul li a span{
text-transform:capitalize;
display:inline-block;
}
#sidebar ul li a i {
position: relative;
margin-right: 10px;
top: 5px;
color: #555555;
margin-left: 10px;
}
/* ---------------------------------------------------
sidebar end
----------------------------------------------------- */
/*=======================================================
main-content navbar-design start
===============================================*/
#content {
position: relative;
transition: all 0.3s;
background-color: #EEEEEE;
}
.top-navbar{
width:100%;
z-index:9;
position:relative;
}
.main-content{
padding:10px 20px 0px 20px;
position: relative;
width: 100%;
}
.navbar{
background-color: #2196F3;
color: #FFFFFF;
}
.navbar-brand {
color: #FFFFFF;
}
.navbar button{
background-color:transparent;
border:none;
}
.navbar button span{
color:#fff;
}
#sidebarCollapse{
border-radius:50%;
width:45px;
height:45px;
text-align:center;
line-height:45px;
margin-right:20px;
border:none;
color: #FFFFFF;
background-color: rgba(0, 0, 0, 0.09);
}
#sidebarCollapse span {
margin: 9px;
padding: 0px;
}
.navbar-nav > li.active{
color: #FFFFFF;
border-radius:4px;
background-color: rgba(0, 0, 0, 0.08);
}
.navbar-nav > li > a {
color: #FFFFFF;
}
.navbar .notification {
position: absolute;
top: 5px;
right: 10px;
display: block;
font-size: 9px;
border: 0px;
font-size: 10px;
background: #d9534f;
min-width: 15px;
text-align: center;
padding: 1px 5px;
height: 15px;
border-radius: 2px;
line-height: 14px;
}
.navbar-nav > li.show .dropdown-menu {
transform: translate3d(0, 0, 0);
opacity:1;
visibility:visible;
}
.dropdown-menu li > a {
font-size: 13px;
padding: 10px 20px;
margin: 0 5px;
border-radius: 2px;
font-weight: 400;
transition: all 150ms linear;
}
.navbar-nav > .active > a:focus {
color: #FFFFFF;
background-color: rgba(0, 0, 0, 0.08);
}
.navbar-nav li a {
position: relative;
display: block;
padding: 10px 15px!important;
}
/*=======================================================
main-content navbar-design end
===============================================*/
/*=======================================================
main-content navbar-design start
===============================================*/
/*=======================================================
main-content inner design like card start
===============================================*/
.card {
margin: 10px 0;
}
.card {
border-radius: 0px!important;
}
.card {
display: inline-block;
position: relative;
border:none!important;
width: 100%;
margin:15px 0;
box-shadow: 0 1px 2px rgb(0 0 0 / 8%);
border-radius: 6px;
color: rgba(0,0,0, 0.87);
background: #fff;
}
.card-stats .card-header {
float: left;
text-align: center;
}
.card .card-header {
padding: 15px 20px 0;
z-index: 3;
background-color:#fff!important;
border-bottom:none;
}
.card .card-footer .stats .material-icons {
position: relative;
top: 4px;
font-size: 16px;
}
.card-stats .card-header span {
font-size: 36px;
line-height: 56px;
width: 56px;
height: 56px;
}
.icon.icon-warning {
color: #ff9800;
}
.icon.icon-rose {
color: #e91e63;
}
.icon.icon-success {
color: #4caf50;
}
.icon.icon-info {
color: #00bcd4;
}
.card .card-footer {
margin: 0 7px 0px;
padding-top: 10px;
background-color:#fff;
border-top: 1px solid #eeeeee;
}
.text-info {
color: #03A9F4!important;
}
.card-stats .card-content {
text-align: right;
padding-top: 10px;
}
.card .card-content {
padding: 15px 20px;
position: relative;
}
.card .card-content .category {
margin-bottom: 0;
}
.card .category:not([class*="text-"]) {
color: #555555;
font-size: 14px;
font-weight: 400;
}
.card .card-title:not(.card-calendar .card-title) {
margin-top: 0;
margin-bottom: 5px;
}
.card-stats .card-title {
margin: 0;
}
.card .card-footer .stats {
line-height: 22px;
color: #555555;
font-size: 15px;
}
.card .card-footer div {
display: inline-block;
}
.card .card-header-text h4{
margin-top: 0;
margin-bottom: 3px;
font-size:19px;
font-weight: 400;
color: #222222;
text-decoration: none;
}
.table > thead > tr > th {
border-bottom-width: 1px;
font-size: 16px;
font-weight: 400;
}
.card .card-content {
padding: 15px 20px;
position: relative;
}
.streamline .sl-primary {
border-left-color: #188ae2;
}
.streamline .sl-item {
position: relative;
padding-bottom: 12px;
border-left: 1px solid #ccc;
}
.streamline .sl-item:before {
content: '';
position: absolute;
left: -6px;
top: 0;
background-color: #ccc;
width: 12px;
height: 12px;
border-radius: 100%;
}
.streamline .sl-primary:before, .streamline .sl-primary:last-child:after {
background-color: #188ae2;
}
.streamline .sl-danger:before, .streamline .sl-danger:last-child:after {
background-color: #ff5b5b;
}
.streamline .sl-success {
border-left-color: #10c469;
}
.streamline .sl-success:before, .streamline .sl-success:last-child:after {
background-color: #10c469;
}
.streamline .sl-warning {
border-left-color: #f9c851;
}
.streamline .sl-warning:before, .streamline .sl-warning:last-child:after {
background-color: #f9c851;
}
.streamline .sl-danger {
border-left-color: #ff5b5b;
}
.streamline .sl-item .sl-content {
margin-left: 24px;
}
.streamline .sl-item .text-muted {
color: inherit;
opacity: .6;
font-size:12px;
}
.streamline .sl-item p {
font-size:14px;
color:#333;
}
/*=======================================================
main-content inner design like card end
===============================================*/
/*=============================================
footer design start
=========================================*/
.footer {
border-top: 1px solid #e7e7e7;
}
footer {
padding: 10px 0;
position:relative;
width:100%;
}
footer ul li {
display: inline-block;
}
footer ul li a {
color: inherit;
padding: 15px;
font-weight: 500;
font-size: 12px;
text-transform: uppercase;
border-radius: 3px;
text-decoration: none;
position: relative;
display: block;
}
footer .copyright {
padding: 15px;
font-size:14px;
margin: 0;
}
/*=============================================
footer design end
=========================================*/
#sidebar.show-nav,.body-overlay.show-nav{
transform:translatex(0%);
opacity:1;
display:block;
visibility:visible;
z-index:15;
}
/* ---------------------------------------------------
MEDIAQUERIES
----------------------------------------------------- */
@media only screen and (min-width:992px){
#sidebar.active {
width:80px;
height:100%!important;
position:absolute!important;
overflow:visible!important;
top:0!important;
z-index:666;
float:left!important;
bottom: 0!important;
}
#sidebar.active .sidebar-header h3 span {
display:none;
transition:all 0.5s ease;
}
#sidebar.active ul li a span{
display:none;
transition:all 0.5s ease;
}
#sidebar.active .dropdown-toggle::after {
display:none;
transition:all 0.5s ease;
}
#content {
width: calc(100% - 260px);
position: relative;
float: right;
transition: all 0.3s;
background-color: #EEEEEE;
}
#content.active {
width: calc(100% - 80px);
}
#sidebar.active .menu {
position: absolute;
left: 81px;
background-color: white;
width: 180px;
height: auto;
margin: 5px 0;
top: 0;
border: 1px solid #dcd9d9;
z-index: 4;
}
}
@media only screen and (min-width:992px){
.dropdown-menu {
border: 0;
box-shadow: 0 2px 5px 0 rgb(0 0 0 / 26%);
transform: translate3d(0, -20px, 0);
visibility: hidden;
transition: all 150ms linear;
display: block;
min-width:15rem;
right: 0;
left: auto;
opacity: 0;
}
}
/*===============small-screen overlay sidebar design media queries==============*/
@media only screen and (max-width:992px){
#sidebar {
position:fixed;
top: 0;
bottom:0;
z-index: 10;
width: 260px;
transform:translatex(-100%);
transition: all 150ms linear;
box-shadow:none!important;
}
.body-overlay{
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
display:none;
visibility:hidden;
opacity:0;
z-index:3;
transition: all 150ms linear;
background-color:rgba(0,0,0,0.5);
}
}
/*===============small-screen overlay sidebar design media queries==============*/
/* ---------------------------------------------------
MEDIAQUERIES
----------------------------------------------------- */

129
public/css/style.css Normal file
View File

@ -0,0 +1,129 @@
* {
margin: 0;
padding: 0; }
*,
::after,
::before {
-webkit-box-sizing: border-box;
box-sizing: border-box; }
a {
text-decoration: none;
-webkit-transition: all 0.5s ease-in-out 0s;
-o-transition: all 0.5s ease-in-out 0s;
transition: all 0.5s ease-in-out 0s; }
a:hover {
text-decoration: none; }
/*-----------------------------
News Ticker
------------------------------*/
.acme-news-ticker {
background: #fff;
position: relative;
height: 45px;
border: 1px solid #1974d2;
margin-top: 45px; }
@media (min-width: 768px) {
.acme-news-ticker {
margin-top: 0; } }
.acme-news-ticker-label {
background: #1974d2;
padding: 10px;
width: auto;
float: left;
margin-right: 15px;
line-height: normal;
height: 100%;
color: #fff; }
@media (max-width: 575px) {
.acme-news-ticker-label {
position: absolute;
top: -45px; } }
.acme-news-ticker-box {
height: 100%;
padding-top: 10px;
overflow: hidden; }
@media (max-width: 575px) {
.acme-news-ticker-box {
padding-left: 10px;
padding-right: 120px; } }
.acme-news-ticker-box ul {
width: 100%;
list-style-type: none !important;
padding: 0;
margin: 0; }
.acme-news-ticker-box ul li a {
text-decoration: none; }
.acme-news-ticker-controls {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
position: absolute;
height: 100%;
right: 0;
top: 0; }
.acme-news-ticker-controls button {
height: 100%;
background: #f6f6f6;
padding: 0;
width: 40px;
border-color: #eeeeee;
border-style: solid;
border-width: 0 0 0 1px;
cursor: pointer;
display: inline-block; }
.acme-news-ticker-controls button:hover {
background: #eeeeee; }
.acme-news-ticker-controls button.acme-news-ticker-arrow {
margin: 0;
display: inline-block;
position: relative; }
.acme-news-ticker-controls button.acme-news-ticker-arrow:after {
border-color: #999;
border-bottom-style: solid;
border-bottom-width: 2px;
border-right-style: solid;
border-right-width: 2px;
content: '';
display: inline-block;
height: 8px;
left: 50%;
position: absolute;
top: 50%;
width: 8px; }
.acme-news-ticker-controls button.acme-news-ticker-pause {
position: relative;
display: inline-block; }
.acme-news-ticker-controls button.acme-news-ticker-pause:before {
position: absolute;
content: "";
width: 10px;
height: 10px;
border-color: #999;
border-style: solid;
border-width: 0 2px 0;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
left: 50%;
top: 50%; }
.acme-news-ticker-controls.acme-news-ticker-horizontal-controls button.acme-news-ticker-prev:after {
-webkit-transform: translate(-50%, -50%) rotate(135deg);
-ms-transform: translate(-50%, -50%) rotate(135deg);
transform: translate(-50%, -50%) rotate(135deg); }
.acme-news-ticker-controls.acme-news-ticker-horizontal-controls button.acme-news-ticker-next:after {
-webkit-transform: translate(-50%, -50%) rotate(315deg);
-ms-transform: translate(-50%, -50%) rotate(315deg);
transform: translate(-50%, -50%) rotate(315deg); }
.acme-news-ticker-controls.acme-news-ticker-vertical-controls button.acme-news-ticker-prev:after {
-webkit-transform: translate(-50%, -50%) rotate(225deg);
-ms-transform: translate(-50%, -50%) rotate(225deg);
transform: translate(-50%, -50%) rotate(225deg); }
.acme-news-ticker-controls.acme-news-ticker-vertical-controls button.acme-news-ticker-next:after {
-webkit-transform: translate(-50%, -50%) rotate(405deg);
-ms-transform: translate(-50%, -50%) rotate(405deg);
transform: translate(-50%, -50%) rotate(405deg); }
/*# sourceMappingURL=style.css.map */

BIN
public/img/bg_cms.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

1
public/img/ic_error.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 57.834 57.955"><defs><style>.a{fill:#f4825c;stroke:#707070;}.b{fill:#e74610;}.c{stroke:none;}.d{fill:none;}</style></defs><g transform="translate(-0.498 0.199)"><g transform="translate(0 0)"><g class="a" transform="translate(1.009 0.934)"><circle class="c" cx="27.989" cy="27.989" r="27.989"/><circle class="d" cx="27.989" cy="27.989" r="27.489"/></g><g transform="translate(-26.502 -27.6)"><g transform="translate(27 27.4)"><path class="b" d="M55.917,85.355A28.978,28.978,0,1,1,84.834,56.317,29.012,29.012,0,0,1,55.917,85.355Zm0-54.31A25.272,25.272,0,1,0,81.189,56.317,25.253,25.253,0,0,0,55.917,31.045Z" transform="translate(-27 -27.4)"/><g transform="translate(18.529 18.65)"><path class="b" d="M59.638,63.344a1.827,1.827,0,0,1-1.337-.486l-8.5-8.5a1.762,1.762,0,0,1,0-2.551l8.5-8.5a1.8,1.8,0,0,1,2.551,2.551l-7.168,7.168,7.168,7.169a1.762,1.762,0,0,1,0,2.551A1.234,1.234,0,0,1,59.638,63.344Z" transform="translate(-40.745 -42.75)"/><path class="b" d="M44.133,63.323a1.827,1.827,0,0,1-1.336-.486,1.762,1.762,0,0,1,0-2.551l7.169-7.169L42.8,45.948A1.8,1.8,0,0,1,45.348,43.4l8.5,8.5a1.762,1.762,0,0,1,0,2.551l-8.5,8.5A1.814,1.814,0,0,1,44.133,63.323Z" transform="translate(-42.25 -42.729)"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 58.184 58.184"><defs><style>.a{fill:#56b68b;stroke:#707070;}.b{fill:#018952;fill-rule:evenodd;}.c{stroke:none;}.d{fill:none;}</style></defs><g transform="translate(-138.502 -248.613)"><g transform="translate(138.502 248.613)"><g transform="translate(0 0)"><g class="a" transform="translate(1.009 0.934)"><circle class="c" cx="27.989" cy="27.989" r="27.989"/><circle class="d" cx="27.989" cy="27.989" r="27.489"/></g><path class="b" d="M47.664,22.747l2.3,2.3L31.8,43.209l-2.3,2.3-2.3-2.3-8.978-8.978,2.3-2.3L29.5,40.913ZM34.092,5A29.092,29.092,0,1,1,5,34.092,29.079,29.079,0,0,1,34.092,5Zm0,3.967A25.16,25.16,0,1,1,8.967,34.092,25.173,25.173,0,0,1,34.092,8.967Z" transform="translate(-5 -5)"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 763 B

BIN
public/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

BIN
public/img/logo_unioil.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

7
public/js/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2
public/js/jquery-3.3.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2
public/js/jquery-3.3.1.slim.min.js vendored Normal file

File diff suppressed because one or more lines are too long

6
public/js/jquery.js vendored Normal file

File diff suppressed because one or more lines are too long

5
public/js/popper.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Unioil - @yield('title')</title>
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<head>
<!-- ... other meta tags -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
<!-- ... other meta tags -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
</head>
@if(app()->environment('local'))
<script>
localStorage.setItem('debug', 'awesome-react-app:*');
</script>
@endif
</head>
<body>
<div id="root" class="app-container h-100">
@yield('content')
</div>
<script src="{{ asset('js/app.js') }}"></script>
@stack('scripts')
</body>
</html>

View File

@ -0,0 +1,243 @@
<!Doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
<title>cms dashboard
</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="css/bootstrap.min.css">
<!----css3---->
<link rel="stylesheet" href="css/custom.css">
<!-- SLIDER REVOLUTION 4.x CSS SETTINGS -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" integrity="sha512-..." crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>
<body>
<div class="wrapper">
<div class="body-overlay"></div>
<!-- Sidebar -->
<nav id="sidebar">
<div class="sidebar-header">
<h3><img src="img/logo.png" class="img-fluid"/><span></span></h3>
</div>
<ul class="list-unstyled components">
<li class="active ">
<a href="#" class="dashboard "><i class="fa-solid fa-gauge" ></i><span>User Management</span></a>
</li>
<li>
<a href="#" class="dashboard"><i class="fa-solid fa-bell"></i><span>Notifications</span></a>
</li>
<li class="dropdown">
<a href="#homeSubmenu1" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="fa-solid fa-users-gear"></i><span>Member Management</span></a>
<ul class="collapse list-unstyled menu" id="homeSubmenu1">
<li><a href="#">Card Member</a></li>
<li><a href="#">Locked Accounts</a></li>
</ul>
</li>
<li class="dropdown">
<a href="#pageSubmenu2" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="fa-solid fa-mobile-screen"></i><span>Home Page (Mobile)</span></a>
<ul class="collapse list-unstyled menu" id="pageSubmenu2">
<li><a href="#">Photo Slider</a></li>
</ul>
</li>
<li>
<a href="#" class="dashboard"><i class="fa-solid fa-tag"></i><span>Promotions</span></a>
</li>
<li>
<a href="#" class="dashboard"><i class="fa-solid fa-wallet"></i><span>Top-Up</span></a>
</li>
<li class="dropdown">
<a href="#pageSubmenu3" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="fa-solid fa-circle-info"></i><span>About Us</span></a>
<ul class="collapse list-unstyled menu" id="pageSubmenu3">
<li><a href="#">Card Types</a></li>
<li><a href="#">Terms & Privacy</a></li>
</ul>
</li>
<li class="dropdown">
<a href="#pageSubmenu4" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="fa-solid fa-chart-column"></i><span>Reports</span></a>
<ul class="collapse list-unstyled menu" id="pageSubmenu4">
<li><a href="#">Registration Report</a></li>
<li><a href="#">Top-Up Usage Report</a></li>
<li><a href="#">Mobile Usage Report</a></li>
<li><a href="#">Station Rating Report</a></li>
</ul>
</li>
<li>
<a href="#"><i class="fa-solid fa-sliders"></i><span>System Parameters</span></a>
</li>
<li class="dropdown">
<a href="#pageSubmenu5" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="fa-solid fa-location-dot"></i><span>Station Locator</span></a>
<ul class="collapse list-unstyled menu" id="pageSubmenu5">
<li><a href="#">Branches</a></li>
<li><a href="#">Stations</a></li>
<li><a href="#">Fuels</a></li>
</ul>
</li>
</ul>
</nav>
<!-- Page Content -->
<div id="content">
<div class="top-navbar">
<nav class="navbar navbar-expand-lg">
<div class="container-fluid">
<button type="button" id="sidebarCollapse" class="d-xl-block d-lg-block d-md-mone d-none">
<span class="fa-solid fa-arrow-left"></span>
</button>
<a class="navbar-brand" href="#"> Dashboard </a>
<button class="d-inline-block d-lg-none ml-auto more-button" type="button" data-toggle="collapse"
data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="material-icons">more_vert</span>
</button>
<div class="collapse navbar-collapse d-lg-block d-xl-block d-sm-none d-md-none d-none" id="navbarSupportedContent">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle d-flex align-items-center gap-2" href="#" role="button" data-toggle="dropdown">
<span>LBTek Systems</span>
<i class="fa-solid fa-user-circle"></i>
</a>
<ul class="dropdown-menu dropdown-menu-end dropdown-menu-sm">
<li>
<a class="dropdown-item d-flex align-items-center gap-2" href="/profile">
<i class="fa-solid fa-user" style="font-size:16px; color:gray;"></i>
<span>My Profile</span>
</a>
</li>
<li>
<a class="dropdown-item d-flex align-items-center gap-2" href="/logout">
<i class="fa-solid fa-right-from-bracket" style="font-size:16px; color:gray;"></i>
<span>Logout</span>
</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
</div>
<div class="main-content">
<div class="row ">
<div class="col-lg-7 col-md-12">
<div class="card" style="min-height: 500px">
<div class="card-header card-header-text">
<h4 class="card-title">Employees Stats</h4>
<p class="category">New employees on 15th December, 2016</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="js/jquery-3.3.1.slim.min.js"></script>
<script src="js/popper.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#sidebarCollapse').on('click', function () {
$('#sidebar').toggleClass('active');
$('#content').toggleClass('active');
});
$('.more-button,.body-overlay').on('click', function () {
$('#sidebar,.body-overlay').toggleClass('show-nav');
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,568 @@
<!Doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
<title>cms dashboard
</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="css/bootstrap.min.css">
<!----css3---->
<link rel="stylesheet" href="css/custom.css">
<!-- SLIDER REVOLUTION 4.x CSS SETTINGS -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700;900&display=swap" rel="stylesheet">
<!--google material icon-->
<link href="https://fonts.googleapis.com/css2?family=Material+Icons"
rel="stylesheet">
</head>
<body>
<div class="wrapper">
<div class="body-overlay"></div>
<!-- Sidebar -->
<nav id="sidebar">
<div class="sidebar-header">
<h3><img src="img/logo.png" class="img-fluid"/><span>Vishweb design</span></h3>
</div>
<ul class="list-unstyled components">
<li class="active">
<a href="#" class="dashboard"><i class="material-icons">dashboard</i><span>Dashboard</span></a>
</li>
<div class="small-screen navbar-display">
<li class="dropdown d-lg-none d-md-block d-xl-none d-sm-block">
<a href="#homeSubmenu0" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="material-icons">notifications</i><span> 4 notification</span></a>
<ul class="collapse list-unstyled menu" id="homeSubmenu0">
<li>
<a href="#">You have 5 new messages</a>
</li>
<li>
<a href="#">You're now friend with Mike</a>
</li>
<li>
<a href="#">Wish Mary on her birthday!</a>
</li>
<li>
<a href="#">5 warnings in Server Console</a>
</li>
</ul>
</li>
<li class="d-lg-none d-md-block d-xl-none d-sm-block">
<a href="#"><i class="material-icons">apps</i><span>apps</span></a>
</li>
<li class="d-lg-none d-md-block d-xl-none d-sm-block">
<a href="#"><i class="material-icons">person</i><span>user</span></a>
</li>
<li class="d-lg-none d-md-block d-xl-none d-sm-block">
<a href="#"><i class="material-icons">settings</i><span>setting</span></a>
</li>
</div>
<li class="dropdown">
<a href="#homeSubmenu1" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="material-icons">aspect_ratio</i><span>Layouts</span></a>
<ul class="collapse list-unstyled menu" id="homeSubmenu1">
<li>
<a href="#">Home 1</a>
</li>
<li>
<a href="#">Home 2</a>
</li>
<li>
<a href="#">Home 3</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#pageSubmenu2" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="material-icons">apps</i><span>widgets</span></a>
<ul class="collapse list-unstyled menu" id="pageSubmenu2">
<li>
<a href="#">Page 1</a>
</li>
<li>
<a href="#">Page 2</a>
</li>
<li>
<a href="#">Page 3</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#pageSubmenu3" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="material-icons">equalizer</i>
<span>chart</span></a>
<ul class="collapse list-unstyled menu" id="pageSubmenu3">
<li>
<a href="#">Page 1</a>
</li>
<li>
<a href="#">Page 2</a>
</li>
<li>
<a href="#">Page 3</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#pageSubmenu4" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="material-icons">extension</i><span>ui element</span></a>
<ul class="collapse list-unstyled menu" id="pageSubmenu4">
<li>
<a href="#">Page 1</a>
</li>
<li>
<a href="#">Page 2</a>
</li>
<li>
<a href="#">Page 3</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#pageSubmenu5" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="material-icons">border_color</i><span>forms</span></a>
<ul class="collapse list-unstyled menu" id="pageSubmenu5">
<li>
<a href="#">Page 1</a>
</li>
<li>
<a href="#">Page 2</a>
</li>
<li>
<a href="#">Page 3</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#pageSubmenu6" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="material-icons">grid_on</i><span>tables</span></a>
<ul class="collapse list-unstyled menu" id="pageSubmenu6">
<li>
<a href="#">Page 1</a>
</li>
<li>
<a href="#">Page 2</a>
</li>
<li>
<a href="#">Page 3</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#pageSubmenu7" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<i class="material-icons">content_copy</i><span>Pages</span></a>
<ul class="collapse list-unstyled menu" id="pageSubmenu7">
<li>
<a href="#">Page 1</a>
</li>
<li>
<a href="#">Page 2</a>
</li>
<li>
<a href="#">Page 3</a>
</li>
</ul>
</li>
<li class="">
<a href="#"><i class="material-icons">date_range</i><span>copy</span></a>
</li>
<li class="">
<a href="#"><i class="material-icons">library_books</i><span>Calender</span></a>
</li>
</ul>
</nav>
<!-- Page Content -->
<div id="content">
<div class="top-navbar">
<nav class="navbar navbar-expand-lg">
<div class="container-fluid">
<button type="button" id="sidebarCollapse" class="d-xl-block d-lg-block d-md-mone d-none">
<span class="material-icons">arrow_back_ios</span>
</button>
<a class="navbar-brand" href="#"> Dashboard </a>
<button class="d-inline-block d-lg-none ml-auto more-button" type="button" data-toggle="collapse"
data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="material-icons">more_vert</span>
</button>
<div class="collapse navbar-collapse d-lg-block d-xl-block d-sm-none d-md-none d-none" id="navbarSupportedContent">
<ul class="nav navbar-nav ml-auto">
<li class="dropdown nav-item active">
<a href="#" class="nav-link" data-toggle="dropdown">
<span class="material-icons">notifications</span>
<span class="notification">4</span>
</a>
<ul class="dropdown-menu">
<li>
<a href="#">You have 5 new messages</a>
</li>
<li>
<a href="#">You're now friend with Mike</a>
</li>
<li>
<a href="#">Wish Mary on her birthday!</a>
</li>
<li>
<a href="#">5 warnings in Server Console</a>
</li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<span class="material-icons">apps</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<span class="material-icons">person</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<span class="material-icons">settings</span>
</a>
</li>
</ul>
</div>
</div>
</nav>
</div>
<div class="main-content">
<div class="row">
<div class="col-lg-3 col-md-6 col-sm-6">
<div class="card card-stats">
<div class="card-header">
<div class="icon icon-warning">
<span class="material-icons">equalizer</span>
</div>
</div>
<div class="card-content">
<p class="category"><strong>Visits</strong></p>
<h3 class="card-title">70,340</h3>
</div>
<div class="card-footer">
<div class="stats">
<i class="material-icons text-info">info</i>
<a href="#pablo">See detailed report</a>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 col-sm-6">
<div class="card card-stats">
<div class="card-header">
<div class="icon icon-rose">
<span class="material-icons">shopping_cart</span>
</div>
</div>
<div class="card-content">
<p class="category"><strong>Orders</strong></p>
<h3 class="card-title">102</h3>
</div>
<div class="card-footer">
<div class="stats">
<i class="material-icons">local_offer</i> Product-wise sales
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 col-sm-6">
<div class="card card-stats">
<div class="card-header">
<div class="icon icon-success">
<span class="material-icons">
attach_money
</span>
</div>
</div>
<div class="card-content">
<p class="category"><strong>Revenue</strong></p>
<h3 class="card-title">$23,100</h3>
</div>
<div class="card-footer">
<div class="stats">
<i class="material-icons">date_range</i> Weekly sales
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 col-sm-6">
<div class="card card-stats">
<div class="card-header">
<div class="icon icon-info">
<span class="material-icons">
follow_the_signs
</span>
</div>
</div>
<div class="card-content">
<p class="category"><strong>Followers</strong></p>
<h3 class="card-title">+245</h3>
</div>
<div class="card-footer">
<div class="stats">
<i class="material-icons">update</i> Just Updated
</div>
</div>
</div>
</div>
</div>
<div class="row ">
<div class="col-lg-7 col-md-12">
<div class="card" style="min-height: 485px">
<div class="card-header card-header-text">
<h4 class="card-title">Employees Stats</h4>
<p class="category">New employees on 15th December, 2016</p>
</div>
<div class="card-content table-responsive">
<table class="table table-hover">
<thead class="text-primary">
<tr><th>ID</th>
<th>Name</th>
<th>Salary</th>
<th>Country</th>
</tr></thead>
<tbody>
<tr>
<td>1</td>
<td>Bob Williams</td>
<td>$23,566</td>
<td>USA</td>
</tr>
<tr>
<td>2</td>
<td>Mike Tyson</td>
<td>$10,200</td>
<td>Canada</td>
</tr>
<tr>
<td>3</td>
<td>Tim Sebastian</td>
<td>$32,190</td>
<td>Netherlands</td>
</tr>
<tr>
<td>4</td>
<td>Philip Morris</td>
<td>$31,123</td>
<td>Korea, South</td>
</tr>
<tr>
<td>5</td>
<td>Minerva Hooper</td>
<td>$23,789</td>
<td>South Africa</td>
</tr>
<tr>
<td>6</td>
<td>Hulk Hogan</td>
<td>$43,120</td>
<td>Netherlands</td>
</tr>
<tr>
<td>7</td>
<td>Angelina Jolie </td>
<td>$12,140</td>
<td>Australia</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="col-lg-5 col-md-12">
<div class="card" style="min-height: 485px">
<div class="card-header card-header-text">
<h4 class="card-title">Activities</h4>
</div>
<div class="card-content">
<div class="streamline">
<div class="sl-item sl-primary">
<div class="sl-content">
<small class="text-muted">5 mins ago</small>
<p>Williams has just joined Project X</p>
</div>
</div>
<div class="sl-item sl-danger">
<div class="sl-content">
<small class="text-muted">25 mins ago</small>
<p>Jane has sent a request for access to the project folder</p>
</div>
</div>
<div class="sl-item sl-success">
<div class="sl-content">
<small class="text-muted">40 mins ago</small>
<p>Kate added you to her team</p>
</div>
</div>
<div class="sl-item">
<div class="sl-content">
<small class="text-muted">45 minutes ago</small>
<p>John has finished his task</p>
</div>
</div>
<div class="sl-item sl-warning">
<div class="sl-content">
<small class="text-muted">55 mins ago</small>
<p>Jim shared a folder with you</p>
</div>
</div>
<div class="sl-item">
<div class="sl-content">
<small class="text-muted">60 minutes ago</small>
<p>John has finished his task</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<nav class="d-flex">
<ul class="m-0 p-0">
<li>
<a href="#">
Home
</a>
</li>
<li>
<a href="#">
Company
</a>
</li>
<li>
<a href="#">
Portfolio
</a>
</li>
<li>
<a href="#">
Blog
</a>
</li>
</ul>
</nav>
</div>
<div class="col-md-6">
<p class="copyright d-flex justify-content-end"> &copy 2021 Design by
<a href="#">Vishweb Design</a> BootStrap Admin Dashboard
</p>
</div>
</div>
</div>
</footer>
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="js/jquery-3.3.1.slim.min.js"></script>
<script src="js/popper.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#sidebarCollapse').on('click', function () {
$('#sidebar').toggleClass('active');
$('#content').toggleClass('active');
});
$('.more-button,.body-overlay').on('click', function () {
$('#sidebar,.body-overlay').toggleClass('show-nav');
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Login - Laravel</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">
<link rel="icon" type="image/png" href="{{ asset('img/favicon_unioil.ico') }}">
</head>
<body>
<div class="min-vh-100 d-flex">
<!-- Sider -->
<div class="col-md-6 d-none d-md-block" style="background: url('/img/bg_cms.png') center / cover no-repeat;"></div>
<!-- Content and Footer -->
<div class="col-md-6 d-flex flex-column justify-content-between">
<div class="p-4 flex-grow-1">
@yield('content')
</div>
<footer class="text-center py-3" style="font-size: 12px;">
<div class="mx-auto px-0 py-4" style="width: 325px; border-top: 1px solid #e0e0e0; text-align: left; color: #8E8E93;">
By logging in you agree to Unioil's Terms of Service, <br>Privacy Policy and Content Policies.
</div>
</footer>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</body>
</html>

View File

@ -0,0 +1,60 @@
@extends('layouts.login')
@section('content')
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-12 col-md-6">
<img src="{{ asset('img/logo.png') }}" alt="Unioil Logo" class="img-fluid" style="max-width: 150px;">
<div class="mb-3 text-center">
<h4 class="mb-1 fw-bold">Welcome</h4>
<span style="font-size: 14px;" class="text-muted">Sign in to continue</span>
</div>
<form>
<div class="mb-3">
<label class="form-label fw-semibold" style="font-size: 13px; color: #003366;">Enter Username</label>
<input type="text" class="form-control" placeholder="Username">
</div>
<!-- Mockup password input -->
<div class="mb-3">
<label class="form-label fw-semibold text-primary" style="font-size: 13px; color: #003366 !important;">Enter Password</label>
<input type="password" class="form-control" placeholder="Password">
</div>
<div class="row mt-4">
<div class="col-6">
<a href="#" class="text-decoration-none text-primary">Forgot Username</a>
</div>
<div class="col-6 text-end">
<button type="submit" class="btn btn-primary w-100" style="background-color: #E74610; border-color: #E74610;">
Login
</button>
</div>
</div>
</form>
<!-- Modal Simulation -->
<!-- <div class="modal fade show d-block mt-5" tabindex="-1" style="background-color: rgba(0,0,0,0.3); display: none;">
<div class="modal-dialog modal-dialog-centered" style="max-width: 337px;">
<div class="modal-content">
<div class="modal-body">
<h4>Forgot Password</h4>
<p>
To have your password reset, please contact <br>
Unioil's admin at <a href="mailto:admin@unioil.com" class="text-primary">admin@unioil.com</a>
</p>
</div>
<div class="modal-footer justify-content-end">
<button class="btn btn-primary" style="background-color: #E74610; border-color: #E74610; width: 64px;">Ok</button>
</div>
</div>
</div>
</div> -->
</div>
</div>
</div>
@endsection

View File

@ -0,0 +1,102 @@
@php
if (! isset($scrollTo)) {
$scrollTo = 'body';
}
$scrollIntoViewJsSnippet = ($scrollTo !== false)
? <<<JS
(\$el.closest('{$scrollTo}') || document.querySelector('{$scrollTo}')).scrollIntoView()
JS
: '';
@endphp
<div>
@if ($paginator->hasPages())
<nav class="d-flex justify-items-center justify-content-between">
<div class="d-flex justify-content-between flex-fill d-sm-none">
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="page-item disabled" aria-disabled="true">
<span class="page-link">@lang('pagination.previous')</span>
</li>
@else
<li class="page-item">
<button type="button" dusk="previousPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}" class="page-link" wire:click="previousPage('{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled">@lang('pagination.previous')</button>
</li>
@endif
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li class="page-item">
<button type="button" dusk="nextPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}" class="page-link" wire:click="nextPage('{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled">@lang('pagination.next')</button>
</li>
@else
<li class="page-item disabled" aria-disabled="true">
<span class="page-link" aria-hidden="true">@lang('pagination.next')</span>
</li>
@endif
</ul>
</div>
<div class="d-none flex-sm-fill d-sm-flex align-items-sm-center justify-content-sm-between">
<div>
<p class="small text-muted">
{!! __('Showing') !!}
<span class="fw-semibold">{{ $paginator->firstItem() }}</span>
{!! __('to') !!}
<span class="fw-semibold">{{ $paginator->lastItem() }}</span>
{!! __('of') !!}
<span class="fw-semibold">{{ $paginator->total() }}</span>
{!! __('results') !!}
</p>
</div>
<div>
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
<span class="page-link" aria-hidden="true">&lsaquo;</span>
</li>
@else
<li class="page-item">
<button type="button" dusk="previousPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}" class="page-link" wire:click="previousPage('{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled" aria-label="@lang('pagination.previous')">&lsaquo;</button>
</li>
@endif
{{-- Pagination Elements --}}
@foreach ($elements as $element)
{{-- "Three Dots" Separator --}}
@if (is_string($element))
<li class="page-item disabled" aria-disabled="true"><span class="page-link">{{ $element }}</span></li>
@endif
{{-- Array Of Links --}}
@if (is_array($element))
@foreach ($element as $page => $url)
@if ($page == $paginator->currentPage())
<li class="page-item active" wire:key="paginator-{{ $paginator->getPageName() }}-page-{{ $page }}" aria-current="page"><span class="page-link">{{ $page }}</span></li>
@else
<li class="page-item" wire:key="paginator-{{ $paginator->getPageName() }}-page-{{ $page }}"><button type="button" class="page-link" wire:click="gotoPage({{ $page }}, '{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}">{{ $page }}</button></li>
@endif
@endforeach
@endif
@endforeach
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li class="page-item">
<button type="button" dusk="nextPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}" class="page-link" wire:click="nextPage('{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled" aria-label="@lang('pagination.next')">&rsaquo;</button>
</li>
@else
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
<span class="page-link" aria-hidden="true">&rsaquo;</span>
</li>
@endif
</ul>
</div>
</div>
</nav>
@endif
</div>

View File

@ -0,0 +1,53 @@
@php
if (! isset($scrollTo)) {
$scrollTo = 'body';
}
$scrollIntoViewJsSnippet = ($scrollTo !== false)
? <<<JS
(\$el.closest('{$scrollTo}') || document.querySelector('{$scrollTo}')).scrollIntoView()
JS
: '';
@endphp
<div>
@if ($paginator->hasPages())
<nav>
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="page-item disabled" aria-disabled="true">
<span class="page-link">@lang('pagination.previous')</span>
</li>
@else
@if(method_exists($paginator,'getCursorName'))
<li class="page-item">
<button dusk="previousPage" type="button" class="page-link" wire:key="cursor-{{ $paginator->getCursorName() }}-{{ $paginator->previousCursor()->encode() }}" wire:click="setPage('{{$paginator->previousCursor()->encode()}}','{{ $paginator->getCursorName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled">@lang('pagination.previous')</button>
</li>
@else
<li class="page-item">
<button type="button" dusk="previousPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}" class="page-link" wire:click="previousPage('{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled">@lang('pagination.previous')</button>
</li>
@endif
@endif
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
@if(method_exists($paginator,'getCursorName'))
<li class="page-item">
<button dusk="nextPage" type="button" class="page-link" wire:key="cursor-{{ $paginator->getCursorName() }}-{{ $paginator->nextCursor()->encode() }}" wire:click="setPage('{{$paginator->nextCursor()->encode()}}','{{ $paginator->getCursorName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled">@lang('pagination.next')</button>
</li>
@else
<li class="page-item">
<button type="button" dusk="nextPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}" class="page-link" wire:click="nextPage('{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled">@lang('pagination.next')</button>
</li>
@endif
@else
<li class="page-item disabled" aria-disabled="true">
<span class="page-link">@lang('pagination.next')</span>
</li>
@endif
</ul>
</nav>
@endif
</div>

View File

@ -0,0 +1,56 @@
@php
if (! isset($scrollTo)) {
$scrollTo = 'body';
}
$scrollIntoViewJsSnippet = ($scrollTo !== false)
? <<<JS
(\$el.closest('{$scrollTo}') || document.querySelector('{$scrollTo}')).scrollIntoView()
JS
: '';
@endphp
<div>
@if ($paginator->hasPages())
<nav role="navigation" aria-label="Pagination Navigation" class="flex justify-between">
<span>
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md dark:text-gray-600 dark:bg-gray-800 dark:border-gray-600">
{!! __('pagination.previous') !!}
</span>
@else
@if(method_exists($paginator,'getCursorName'))
<button type="button" dusk="previousPage" wire:key="cursor-{{ $paginator->getCursorName() }}-{{ $paginator->previousCursor()->encode() }}" wire:click="setPage('{{$paginator->previousCursor()->encode()}}','{{ $paginator->getCursorName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-blue-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
{!! __('pagination.previous') !!}
</button>
@else
<button
type="button" wire:click="previousPage('{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled" dusk="previousPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-blue-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
{!! __('pagination.previous') !!}
</button>
@endif
@endif
</span>
<span>
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
@if(method_exists($paginator,'getCursorName'))
<button type="button" dusk="nextPage" wire:key="cursor-{{ $paginator->getCursorName() }}-{{ $paginator->nextCursor()->encode() }}" wire:click="setPage('{{$paginator->nextCursor()->encode()}}','{{ $paginator->getCursorName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-blue-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
{!! __('pagination.next') !!}
</button>
@else
<button type="button" wire:click="nextPage('{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled" dusk="nextPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-blue-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
{!! __('pagination.next') !!}
</button>
@endif
@else
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md dark:text-gray-600 dark:bg-gray-800 dark:border-gray-600">
{!! __('pagination.next') !!}
</span>
@endif
</span>
</nav>
@endif
</div>

View File

@ -0,0 +1,126 @@
@php
if (! isset($scrollTo)) {
$scrollTo = 'body';
}
$scrollIntoViewJsSnippet = ($scrollTo !== false)
? <<<JS
(\$el.closest('{$scrollTo}') || document.querySelector('{$scrollTo}')).scrollIntoView()
JS
: '';
@endphp
<div>
@if ($paginator->hasPages())
<nav role="navigation" aria-label="Pagination Navigation" class="flex items-center justify-between">
<div class="flex justify-between flex-1 sm:hidden">
<span>
@if ($paginator->onFirstPage())
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
{!! __('pagination.previous') !!}
</span>
@else
<button type="button" wire:click="previousPage('{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled" dusk="previousPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}.before" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-blue-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
{!! __('pagination.previous') !!}
</button>
@endif
</span>
<span>
@if ($paginator->hasMorePages())
<button type="button" wire:click="nextPage('{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" wire:loading.attr="disabled" dusk="nextPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}.before" class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-blue-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
{!! __('pagination.next') !!}
</button>
@else
<span class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md dark:text-gray-600 dark:bg-gray-800 dark:border-gray-600">
{!! __('pagination.next') !!}
</span>
@endif
</span>
</div>
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
<div>
<p class="text-sm text-gray-700 leading-5 dark:text-gray-400">
<span>{!! __('Showing') !!}</span>
<span class="font-medium">{{ $paginator->firstItem() }}</span>
<span>{!! __('to') !!}</span>
<span class="font-medium">{{ $paginator->lastItem() }}</span>
<span>{!! __('of') !!}</span>
<span class="font-medium">{{ $paginator->total() }}</span>
<span>{!! __('results') !!}</span>
</p>
</div>
<div>
<span class="relative z-0 inline-flex rtl:flex-row-reverse rounded-md shadow-sm">
<span>
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<span aria-disabled="true" aria-label="{{ __('pagination.previous') }}">
<span class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default rounded-l-md leading-5 dark:bg-gray-800 dark:border-gray-600" aria-hidden="true">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
</span>
</span>
@else
<button type="button" wire:click="previousPage('{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" dusk="previousPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}.after" class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-l-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:border-blue-300 focus:ring ring-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:active:bg-gray-700 dark:focus:border-blue-800" aria-label="{{ __('pagination.previous') }}">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
</button>
@endif
</span>
{{-- Pagination Elements --}}
@foreach ($elements as $element)
{{-- "Three Dots" Separator --}}
@if (is_string($element))
<span aria-disabled="true">
<span class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 cursor-default leading-5 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300">{{ $element }}</span>
</span>
@endif
{{-- Array Of Links --}}
@if (is_array($element))
@foreach ($element as $page => $url)
<span wire:key="paginator-{{ $paginator->getPageName() }}-page{{ $page }}">
@if ($page == $paginator->currentPage())
<span aria-current="page">
<span class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 dark:bg-gray-800 dark:border-gray-600">{{ $page }}</span>
</span>
@else
<button type="button" wire:click="gotoPage({{ $page }}, '{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 hover:text-gray-500 focus:z-10 focus:outline-none focus:border-blue-300 focus:ring ring-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-400 dark:hover:text-gray-300 dark:active:bg-gray-700 dark:focus:border-blue-800" aria-label="{{ __('Go to page :page', ['page' => $page]) }}">
{{ $page }}
</button>
@endif
</span>
@endforeach
@endif
@endforeach
<span>
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<button type="button" wire:click="nextPage('{{ $paginator->getPageName() }}')" x-on:click="{{ $scrollIntoViewJsSnippet }}" dusk="nextPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}.after" class="relative inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-r-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:border-blue-300 focus:ring ring-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:active:bg-gray-700 dark:focus:border-blue-800" aria-label="{{ __('pagination.next') }}">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
</svg>
</button>
@else
<span aria-disabled="true" aria-label="{{ __('pagination.next') }}">
<span class="relative inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default rounded-r-md leading-5 dark:bg-gray-800 dark:border-gray-600" aria-hidden="true">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
</svg>
</span>
</span>
@endif
</span>
</span>
</div>
</div>
</nav>
@endif
</div>

File diff suppressed because one or more lines are too long

View File

@ -2,6 +2,11 @@
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
return view('login');
});
Route::get('/dashboard', function () {
return view('dashboard');
});

0
storage/app/.gitignore vendored Normal file → Executable file
View File

0
storage/app/private/.gitignore vendored Normal file → Executable file
View File

0
storage/app/public/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/cache/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/cache/data/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/sessions/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/testing/.gitignore vendored Normal file → Executable file
View File

0
storage/framework/views/.gitignore vendored Normal file → Executable file
View File

0
storage/logs/.gitignore vendored Normal file → Executable file
View File