prepare page for admin and user

dev
Aji Kamaludin 1 year ago
parent 3b139e25f8
commit 32fa189e4f
No known key found for this signature in database
GPG Key ID: 19058F67F0083AD3

@ -4,7 +4,6 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\LoginRequest;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@ -34,7 +33,7 @@ class AuthenticatedSessionController extends Controller
$request->session()->regenerate();
return redirect()->intended(RouteServiceProvider::HOME);
return redirect()->route('dashboard');
}
/**
@ -48,6 +47,6 @@ class AuthenticatedSessionController extends Controller
$request->session()->regenerateToken();
return redirect()->route('login');
return redirect()->route('admin.login');
}
}

@ -59,7 +59,7 @@ class NewPasswordController extends Controller
// the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message.
if ($status == Password::PASSWORD_RESET) {
return redirect()->route('login')->with('status', __($status));
return redirect()->route('admin.login')->with('status', __($status));
}
throw ValidationException::withMessages([

@ -0,0 +1,13 @@
<?php
namespace App\Http\Controllers\Customer;
use App\Http\Controllers\Controller;
class HomeController extends Controller
{
public function index()
{
return inertia('Home/Index/Index');
}
}

@ -37,7 +37,7 @@ class Kernel extends HttpKernel
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\HandleInertiaRequests::class,
// \App\Http\Middleware\HandleInertiaRequests::class,
\Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets::class,
],
@ -66,5 +66,7 @@ class Kernel extends HttpKernel
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'inertia.admin' => \App\Http\Middleware\HandleInertiaRequests::class,
'inertia.customer' => \App\Http\Middleware\HandleInertiaCustomerRequests::class,
];
}

@ -15,7 +15,7 @@ class Authenticate extends Middleware
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
return route('admin.login');
}
}
}

@ -0,0 +1,42 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Inertia\Middleware;
class HandleInertiaCustomerRequests extends Middleware
{
/**
* The root template that is loaded on the first page visit.
*
* @var string
*/
protected $rootView = 'app';
/**
* Determine the current asset version.
*/
public function version(Request $request): string|null
{
return parent::version($request);
}
/**
* Define the props that are shared by default.
*
* @return array<string, mixed>
*/
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'auth' => [
'user' => $request->user(),
],
'flash' => [
'message' => fn () => $request->session()->get('message'),
],
'app_name' => env('APP_NAME', 'App Name'),
]);
}
}

@ -12,7 +12,7 @@ class HandleInertiaRequests extends Middleware
*
* @var string
*/
protected $rootView = 'app';
protected $rootView = 'admin';
/**
* Determine the current asset version.
@ -36,6 +36,7 @@ class HandleInertiaRequests extends Middleware
'flash' => [
'message' => fn () => $request->session()->get('message'),
],
'app_name' => env('APP_NAME', 'App Name'),
]);
}
}

@ -22,7 +22,10 @@ class RedirectIfAuthenticated
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
if ($guard == 'web') {
return redirect()->route('dashboard');
}
return redirect()->route('home.index');
}
}

@ -2,7 +2,6 @@
namespace App\Models;
class CoinReward extends Model
{
protected $fillable = [

@ -8,7 +8,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Customer extends Authenticatable
{
use HasFactory, HasUlids, UserTrackable, SoftDeletes;

@ -17,7 +17,7 @@ class RouteServiceProvider extends ServiceProvider
*
* @var string
*/
public const HOME = '/dashboard';
// public const HOME = '/dashboard';
/**
* Define your route model bindings, pattern filters, and other route configuration.

@ -42,8 +42,8 @@ return [
],
'customer' => [
'driver' => 'session',
'provider' => 'customers'
]
'provider' => 'customers',
],
],
/*

@ -1,7 +1,9 @@
import React from 'react';
import { usePage } from '@inertiajs/react'
import React from 'react'
export default function ApplicationLogo({ className }) {
return (
<h1 className={className}>App Name</h1>
);
const {
props: { app_name },
} = usePage()
return <h1 className={className}>{app_name}</h1>
}

@ -0,0 +1,19 @@
import React from 'react'
import ApplicationLogo from '@/Components/Defaults/ApplicationLogo'
import { Link } from '@inertiajs/react'
export default function CustomerLayout({ children }) {
return (
<div className="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-gray-900">
<div>
<Link href="/">
<ApplicationLogo className="w-auto h-20 fill-current text-gray-500 text-5xl font-bold" />
</Link>
</div>
<div className="w-full max-w-md mt-6 px-6 py-4 bg-white dark:bg-gray-800 shadow-md overflow-hidden sm:rounded-lg">
{children}
</div>
</div>
)
}

@ -1,13 +1,16 @@
import React from 'react';
import { router } from '@inertiajs/react';
import { Sidebar } from 'flowbite-react';
import { HiLogout } from 'react-icons/hi';
import { filterOpenMenu } from './helpers';
import routes from './routes';
import { formatDate } from '@/utils';
import React from 'react'
import { router, usePage } from '@inertiajs/react'
import { Sidebar } from 'flowbite-react'
import { HiLogout } from 'react-icons/hi'
import { filterOpenMenu } from './helpers'
import routes from './routes'
export default function SidebarNav({ user }) {
const menus = routes.filter(item => {
const {
props: { app_name },
} = usePage()
const menus = routes.filter((item) => {
item.open = false
if (!item.show) {
return null
@ -15,7 +18,7 @@ export default function SidebarNav({ user }) {
if (+user.is_superadmin === 1) {
return filterOpenMenu(user, item)
}
if(user.role.permissions.find(p => p.name === item.permission)) {
if (user.role.permissions.find((p) => p.name === item.permission)) {
return item
}
@ -26,33 +29,36 @@ export default function SidebarNav({ user }) {
<Sidebar aria-label="Sidebar with multi-level dropdown example">
<Sidebar.Items>
<Sidebar.ItemGroup>
{menus.map(item => (
{menus.map((item) => (
<div key={item.name}>
{item.items === undefined ? (
<Sidebar.Item
onClick={() => router.visit(item.route)}
icon={item.icon}
active={route().current(item.active)}
>
{item.name}
</Sidebar.Item>
<Sidebar.Item
onClick={() => router.visit(item.route)}
icon={item.icon}
active={route().current(item.active)}
>
{item.name}
</Sidebar.Item>
) : (
<Sidebar.Collapse
icon={item.icon}
label={item.name}
open={item.open}
>
{item.items.map(item => (
<Sidebar.Item
{item.items.map((item) => (
<Sidebar.Item
key={item.name}
onClick={() => router.visit(item.route)}
onClick={() =>
router.visit(item.route)
}
icon={item.icon}
active={route().current(item.active)}
active={route().current(
item.active
)}
>
{item.name}
</Sidebar.Item>
))}
</Sidebar.Collapse>
)}
</div>
@ -64,10 +70,10 @@ export default function SidebarNav({ user }) {
Logout
</Sidebar.Item>
</Sidebar.ItemGroup>
<p className='text-sm font-light text-gray-900 dark:text-gray-100 text-center bottom-4 left-4 pt-10'>
App Name &copy; {(new Date()).getFullYear()}
<p className="text-sm font-light text-gray-900 dark:text-gray-100 text-center bottom-4 left-4 pt-10">
{app_name} &copy; {new Date().getFullYear()}
</p>
</Sidebar.Items>
</Sidebar>
)
}
}

@ -1,43 +1,52 @@
import React, { useEffect } from 'react';
import GuestLayout from '@/Layouts/GuestLayout';
import InputError from '@/Components/Defaults/InputError';
import { Head, Link, useForm } from '@inertiajs/react';
import { Button, TextInput,Label, Checkbox, Spinner } from 'flowbite-react';
import React, { useEffect } from 'react'
import GuestLayout from '@/Layouts/GuestLayout'
import InputError from '@/Components/Defaults/InputError'
import { Head, Link, useForm } from '@inertiajs/react'
import { Button, TextInput, Label, Checkbox, Spinner } from 'flowbite-react'
export default function Login({ status }) {
const { data, setData, post, processing, errors, reset } = useForm({
email: '',
password: '',
remember: '',
});
})
useEffect(() => {
return () => {
reset('password');
};
}, []);
reset('password')
}
}, [])
const onHandleChange = (event) => {
setData(event.target.name, event.target.type === 'checkbox' ? event.target.checked : event.target.value);
};
setData(
event.target.name,
event.target.type === 'checkbox'
? event.target.checked
: event.target.value
)
}
const handleKeyDown = e => {
if(e.code === 'Enter') {
post(route('login'))
const handleKeyDown = (e) => {
if (e.code === 'Enter') {
post(route('admin.login'))
}
}
const submit = (e) => {
e.preventDefault();
e.preventDefault()
post(route('login'));
};
post(route('admin.login'))
}
return (
<GuestLayout>
<Head title="Log in" />
{status && <div className="mb-4 font-medium text-sm text-green-600">{status}</div>}
{status && (
<div className="mb-4 font-medium text-sm text-green-600">
{status}
</div>
)}
<form onSubmit={submit}>
<div>
@ -66,7 +75,7 @@ export default function Login({ status }) {
className="mt-1 block w-full"
autoComplete="current-password"
onChange={onHandleChange}
onKeyDownCapture={e => handleKeyDown(e)}
onKeyDownCapture={(e) => handleKeyDown(e)}
/>
<InputError message={errors.password} className="mt-2" />
@ -74,21 +83,21 @@ export default function Login({ status }) {
<div className="block mt-4">
<label className="flex items-center space-x-2">
<Checkbox id="remember" value={data.remember} onChange={onHandleChange}/>
<Label htmlFor="remember">
Remember me
</Label>
<Checkbox
id="remember"
value={data.remember}
onChange={onHandleChange}
/>
<Label htmlFor="remember">Remember me</Label>
</label>
</div>
<div className="flex items-center justify-end mt-4">
<Button onClick={submit} disabled={processing}>
{processing ? (
<Spinner/>
) : ('Log in')}
{processing ? <Spinner /> : 'Log in'}
</Button>
</div>
</form>
</GuestLayout>
);
)
}

@ -1,10 +1,10 @@
import React, { useEffect } from 'react';
import GuestLayout from '@/Layouts/GuestLayout';
import InputError from '@/Components/Defaults/InputError';
import InputLabel from '@/Components/Defaults/InputLabel';
import PrimaryButton from '@/Components/Defaults/PrimaryButton';
import TextInput from '@/Components/Defaults/TextInput';
import { Head, Link, useForm } from '@inertiajs/react';
import React, { useEffect } from 'react'
import GuestLayout from '@/Layouts/GuestLayout'
import InputError from '@/Components/Defaults/InputError'
import InputLabel from '@/Components/Defaults/InputLabel'
import PrimaryButton from '@/Components/Defaults/PrimaryButton'
import TextInput from '@/Components/Defaults/TextInput'
import { Head, Link, useForm } from '@inertiajs/react'
export default function Register() {
const { data, setData, post, processing, errors, reset } = useForm({
@ -12,23 +12,28 @@ export default function Register() {
email: '',
password: '',
password_confirmation: '',
});
})
useEffect(() => {
return () => {
reset('password', 'password_confirmation');
};
}, []);
reset('password', 'password_confirmation')
}
}, [])
const onHandleChange = (event) => {
setData(event.target.name, event.target.type === 'checkbox' ? event.target.checked : event.target.value);
};
setData(
event.target.name,
event.target.type === 'checkbox'
? event.target.checked
: event.target.value
)
}
const submit = (e) => {
e.preventDefault();
e.preventDefault()
post(route('register'));
};
post(route('register'))
}
return (
<GuestLayout>
@ -85,7 +90,10 @@ export default function Register() {
</div>
<div className="mt-4">
<InputLabel forInput="password_confirmation" value="Confirm Password" />
<InputLabel
forInput="password_confirmation"
value="Confirm Password"
/>
<TextInput
type="password"
@ -96,12 +104,15 @@ export default function Register() {
required
/>
<InputError message={errors.password_confirmation} className="mt-2" />
<InputError
message={errors.password_confirmation}
className="mt-2"
/>
</div>
<div className="flex items-center justify-end mt-4">
<Link
href={route('login')}
href={route('admin.login')}
className="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Already registered?
@ -113,5 +124,5 @@ export default function Register() {
</div>
</form>
</GuestLayout>
);
)
}

@ -0,0 +1,12 @@
import React from 'react'
import { Head } from '@inertiajs/react'
import CustomerLayout from '@/Layouts/CustomerLayout'
export default function Index({ status }) {
return (
<CustomerLayout>
<Head title="Home" />
<h1>This is HOME</h1>
</CustomerLayout>
)
}

@ -1,5 +1,5 @@
import React from 'react';
import { Link, Head } from '@inertiajs/react';
import React from 'react'
import { Link, Head } from '@inertiajs/react'
export default function Welcome(props) {
return (
@ -8,12 +8,18 @@ export default function Welcome(props) {
<div className="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0">
<div className="fixed top-0 right-0 px-6 py-4 sm:block">
{props.auth.user ? (
<Link href={route('dashboard')} className="text-sm text-gray-700 dark:text-gray-500 underline">
<Link
href={route('dashboard')}
className="text-sm text-gray-700 dark:text-gray-500 underline"
>
Dashboard
</Link>
) : (
<>
<Link href={route('login')} className="text-sm text-gray-700 dark:text-gray-500 underline">
<Link
href={route('admin.login')}
className="text-sm text-gray-700 dark:text-gray-500 underline"
>
Log in
</Link>
@ -69,9 +75,13 @@ export default function Welcome(props) {
<div className="ml-12">
<div className="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel has wonderful, thorough documentation covering every aspect of the
framework. Whether you are new to the framework or have previous experience with
Laravel, we recommend reading all of the documentation from beginning to end.
Laravel has wonderful, thorough
documentation covering every aspect of
the framework. Whether you are new to
the framework or have previous
experience with Laravel, we recommend
reading all of the documentation from
beginning to end.
</div>
</div>
</div>
@ -103,9 +113,11 @@ export default function Welcome(props) {
<div className="ml-12">
<div className="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laracasts offers thousands of video tutorials on Laravel, PHP, and JavaScript
development. Check them out, see for yourself, and massively level up your
development skills in the process.
Laracasts offers thousands of video
tutorials on Laravel, PHP, and
JavaScript development. Check them out,
see for yourself, and massively level up
your development skills in the process.
</div>
</div>
</div>
@ -136,9 +148,11 @@ export default function Welcome(props) {
<div className="ml-12">
<div className="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel News is a community driven portal and newsletter aggregating all of the
latest and most important news in the Laravel ecosystem, including new package
releases and tutorials.
Laravel News is a community driven
portal and newsletter aggregating all of
the latest and most important news in
the Laravel ecosystem, including new
package releases and tutorials.
</div>
</div>
</div>
@ -164,45 +178,77 @@ export default function Welcome(props) {
<div className="ml-12">
<div className="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel's robust library of first-party tools and libraries, such as{' '}
<a href="https://forge.laravel.com" className="underline">
Laravel's robust library of first-party
tools and libraries, such as{' '}
<a
href="https://forge.laravel.com"
className="underline"
>
Forge
</a>
,{' '}
<a href="https://vapor.laravel.com" className="underline">
<a
href="https://vapor.laravel.com"
className="underline"
>
Vapor
</a>
,{' '}
<a href="https://nova.laravel.com" className="underline">
<a
href="https://nova.laravel.com"
className="underline"
>
Nova
</a>
, and{' '}
<a href="https://envoyer.io" className="underline">
<a
href="https://envoyer.io"
className="underline"
>
Envoyer
</a>{' '}
help you take your projects to the next level. Pair them with powerful open
help you take your projects to the next
level. Pair them with powerful open
source libraries like{' '}
<a href="https://laravel.com/docs/billing" className="underline">
<a
href="https://laravel.com/docs/billing"
className="underline"
>
Cashier
</a>
,{' '}
<a href="https://laravel.com/docs/dusk" className="underline">
<a
href="https://laravel.com/docs/dusk"
className="underline"
>
Dusk
</a>
,{' '}
<a href="https://laravel.com/docs/broadcasting" className="underline">
<a
href="https://laravel.com/docs/broadcasting"
className="underline"
>
Echo
</a>
,{' '}
<a href="https://laravel.com/docs/horizon" className="underline">
<a
href="https://laravel.com/docs/horizon"
className="underline"
>
Horizon
</a>
,{' '}
<a href="https://laravel.com/docs/sanctum" className="underline">
<a
href="https://laravel.com/docs/sanctum"
className="underline"
>
Sanctum
</a>
,{' '}
<a href="https://laravel.com/docs/telescope" className="underline">
<a
href="https://laravel.com/docs/telescope"
className="underline"
>
Telescope
</a>
, and more.
@ -227,7 +273,10 @@ export default function Welcome(props) {
<path d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"></path>
</svg>
<a href="https://laravel.bigcartel.com" className="ml-1 underline">
<a
href="https://laravel.bigcartel.com"
className="ml-1 underline"
>
Shop
</a>
@ -243,18 +292,22 @@ export default function Welcome(props) {
<path 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"></path>
</svg>
<a href="https://github.com/sponsors/taylorotwell" className="ml-1 underline">
<a
href="https://github.com/sponsors/taylorotwell"
className="ml-1 underline"
>
Sponsor
</a>
</div>
</div>
<div className="ml-4 text-center text-sm text-gray-500 sm:text-right sm:ml-0">
Laravel v{props.laravelVersion} (PHP v{props.phpVersion})
Laravel v{props.laravelVersion} (PHP v
{props.phpVersion})
</div>
</div>
</div>
</div>
</>
);
)
}

@ -0,0 +1,22 @@
import './bootstrap';
import '../css/app.css';
import 'flowbite';
import 'react-toastify/dist/ReactToastify.css';
import React from 'react';
import { createRoot } from 'react-dom/client';
import { createInertiaApp } from '@inertiajs/react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.jsx`, import.meta.glob('./Pages/**/*.jsx')),
setup({ el, App, props }) {
const root = createRoot(el);
root.render(<App {...props} />);
},
progress: { color: '#003bf1' , showSpinner: true, includeCSS: true},
});

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title inertia>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="stylesheet" href="https://fonts.bunny.net/css2?family=Nunito:wght@400;600;700&display=swap">
<!-- Scripts -->
@routes
@viteReactRefresh
@vite(['resources/js/admin.jsx', "resources/js/Pages/{$page['component']}.jsx"])
@inertiaHead
</head>
<body class="font-sans antialiased">
@inertia
</body>
</html>

@ -0,0 +1,43 @@
<?php
use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Controllers\GeneralController;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\RoleController;
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;
Route::middleware(['inertia.admin'])
->prefix('admin')
->group(function () {
Route::middleware(['guest:web'])->group(function () {
Route::get('login', [AuthenticatedSessionController::class, 'create'])
->name('admin.login');
Route::post('login', [AuthenticatedSessionController::class, 'store']);
});
Route::middleware(['auth'])->group(function () {
Route::get('/dashboard', [GeneralController::class, 'index'])->name('dashboard');
Route::get('/maintance', [GeneralController::class, 'maintance'])->name('maintance');
// Admin Profile
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
// Logout
Route::post('logout', [AuthenticatedSessionController::class, 'destroy'])
->name('logout');
// User
Route::get('/users', [UserController::class, 'index'])->name('user.index');
Route::post('/users', [UserController::class, 'store'])->name('user.store');
Route::put('/users/{user}', [UserController::class, 'update'])->name('user.update');
Route::delete('/users/{user}', [UserController::class, 'destroy'])->name('user.destroy');
// Role
Route::resource('/roles', RoleController::class);
});
});

@ -1,9 +1,6 @@
<?php
use App\Http\Controllers\GeneralController;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\RoleController;
use App\Http\Controllers\UserController;
use App\Http\Controllers\Customer\HomeController;
use Illuminate\Support\Facades\Route;
/*
@ -17,28 +14,8 @@ use Illuminate\Support\Facades\Route;
|
*/
Route::get('/', function () {
return redirect()->route('login');
Route::middleware(['inertia.customer'])->group(function () {
Route::get('/', [HomeController::class, 'index'])->name('home.index');
});
Route::middleware(['auth'])->group(function () {
Route::get('/dashboard', [GeneralController::class, 'index'])->name('dashboard');
Route::get('/maintance', [GeneralController::class, 'maintance'])->name('maintance');
// User
Route::get('/users', [UserController::class, 'index'])->name('user.index');
Route::post('/users', [UserController::class, 'store'])->name('user.store');
Route::put('/users/{user}', [UserController::class, 'update'])->name('user.update');
Route::delete('/users/{user}', [UserController::class, 'destroy'])->name('user.destroy');
// Role
Route::resource('/roles', RoleController::class);
});
Route::middleware('auth')->group(function () {
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});
require __DIR__.'/auth.php';
require_once 'admin.php';

Loading…
Cancel
Save