Tutorial Membuat Toko Online Dari Awal Buat Perubahan Pada Layout
Ketika kita menggunakan breeze ini, kita hanya diberi dua pilihan layout, yaitu untuk yang sudah login dan yang belum. Nah jika kita ingin menggunakan satu layout di dalam dua case, maka kita perlu memodifikasinya terlebih dahulu. Karena kita memerlukan layout yang sama walau nantinya user tidak login. Seperti misalnya untuk halaman menampilkan list product dan overview nya.
π π» Modifikasi Navbar
Maka oleh karena itu, silakan ubah nama dari AuthenticatedLayout
menjadi AppLayout
, Setelah itu, silakan buat file baru di dalam direktori resources/js/Layouts
dengan nama Navbar.jsx
, dan dilamanya silakan masukkan kode berikut:
import { Link, usePage } from '@inertiajs/react';
import ApplicationLogo from '@/Components/ApplicationLogo';
import NavLink from '@/Components/NavLink';
import Dropdown from '@/Components/Dropdown';
import ResponsiveNavLink from '@/Components/ResponsiveNavLink';
import { useState } from 'react';
export default function Navbar() {
const { auth } = usePage().props;
const [showingNavigationDropdown, setShowingNavigationDropdown] = useState(false);
return (
<nav className='border-b border-gray-100 bg-white'>
<div className='mx-auto max-w-7xl px-4 sm:px-6 lg:px-8'>
<div className='flex h-16 justify-between'>
<div className='flex'>
<div className='flex shrink-0 items-center'>
<Link href='/'>
<ApplicationLogo className='block h-9 w-auto fill-current text-gray-800' />
</Link>
</div>
<div className='hidden space-x-8 sm:-my-px sm:ml-10 sm:flex'>
<NavLink href={'#'} active={false}>
Products
</NavLink>
</div>
</div>
{auth.user ? (
<div className='hidden sm:ml-6 sm:flex sm:items-center'>
<div className='relative ml-3'>
<Dropdown>
<Dropdown.Trigger>
<span className='inline-flex rounded-md'>
<button
type='button'
className='inline-flex items-center rounded-md border border-transparent bg-white px-3 py-2 text-sm font-medium leading-4 text-gray-500 transition duration-150 ease-in-out hover:text-gray-700 focus:outline-none'>
{auth.user.name}
<svg
className='-mr-0.5 ml-2 h-4 w-4'
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 20 20'
fill='currentColor'>
<path
fillRule='evenodd'
d='M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z'
clipRule='evenodd'
/>
</svg>
</button>
</span>
</Dropdown.Trigger>
<Dropdown.Content>
<Dropdown.Link href={route('dashboard')}>Dashboard</Dropdown.Link>
<Dropdown.Link href={route('profile.edit')}>Profile</Dropdown.Link>
<Dropdown.Link href={route('logout')} method='post' as='button'>
Log Out
</Dropdown.Link>
</Dropdown.Content>
</Dropdown>
</div>
</div>
) : (
<div className='hidden space-x-8 sm:-my-px sm:ml-10 sm:flex'>
<NavLink href={route('login')} active={route().current('login')}>
Login
</NavLink>
<NavLink href={route('register')} active={route().current('register')}>
Register
</NavLink>
</div>
)}
<div className='-mr-2 flex items-center sm:hidden'>
<button
onClick={() => setShowingNavigationDropdown((previousState) => !previousState)}
className='inline-flex items-center justify-center rounded-md p-2 text-gray-400 transition duration-150 ease-in-out hover:bg-gray-100 hover:text-gray-500 focus:bg-gray-100 focus:text-gray-500 focus:outline-none'>
<svg className='h-6 w-6' stroke='currentColor' fill='none' viewBox='0 0 24 24'>
<path
className={!showingNavigationDropdown ? 'inline-flex' : 'hidden'}
strokeLinecap='round'
strokeLinejoin='round'
strokeWidth='2'
d='M4 6h16M4 12h16M4 18h16'
/>
<path
className={showingNavigationDropdown ? 'inline-flex' : 'hidden'}
strokeLinecap='round'
strokeLinejoin='round'
strokeWidth='2'
d='M6 18L18 6M6 6l12 12'
/>
</svg>
</button>
</div>
</div>
</div>
<div className={(showingNavigationDropdown ? 'block' : 'hidden') + ' sm:hidden'}>
<ResponsiveNavLink href='/' active={false}>
Home
</ResponsiveNavLink>
{auth.user ? (
<>
<div className='space-y-1 pb-3 pt-2'>
<ResponsiveNavLink href={route('dashboard')} active={route().current('dashboard')}>
Dashboard
</ResponsiveNavLink>
</div>
<div className='border-t border-gray-200 pb-1 pt-4'>
<div className='px-4'>
<div className='text-base font-medium text-gray-800'>{auth.user.name}</div>
<div className='text-sm font-medium text-gray-500'>{auth.user.email}</div>
</div>
<div className='mt-3 space-y-1'>
<ResponsiveNavLink href={route('dashboard')}>Dashboard</ResponsiveNavLink>
<ResponsiveNavLink href={route('profile.edit')}>Profile</ResponsiveNavLink>
<ResponsiveNavLink method='post' href={route('logout')} as='button'>
Log Out
</ResponsiveNavLink>
</div>
</div>
</>
) : (
<>
<div className='space-y-1 pb-3 pt-2'>
<ResponsiveNavLink href={route('login')} active={route().current('login')}>
Login
</ResponsiveNavLink>
<ResponsiveNavLink href={route('register')} active={route().current('register')}>
Register
</ResponsiveNavLink>
</div>
</>
)}
</div>
</nav>
);
}
Sangat panjang memang, itu hanya karena navbar tersebut sudah responsive, jadi ketika di buka di mobile maka akan berubah menjadi menu dropdown.
Sebelum lanjut, saya akan menunjukkan dulu bahwa di dalam folder resources/js/Layouts
strukturnya seperti ini:
resources/js/Layouts
βββ AppLayout.jsx
βββ GuestLayout.jsx
βββ Navbar.jsx
π π» Setup AppLayout
Buka file AppLayout.jsx
dan silakan modifikasi isinya menjadi seperti ini:
import Navbar from '@/Layouts/Navbar';
export default function AppLayout({ header, children }) {
return (
<div className='min-h-screen bg-gray-100'>
<Navbar />
{header && (
<header className='bg-white shadow'>
<div className='mx-auto max-w-7xl px-4 py-6 sm:px-6 lg:px-8'>{header}</div>
</header>
)}
<main>{children}</main>
</div>
);
}
π π» Modifikasi Dashboard
Kita akan modifikasi file Dashboard.jsx
nya, namun sebelum itu, silakan buat file Container.jsx
tepat pada folder resources/js/Components
seperti ini:
export default function Container({ children }) {
return <div className='mx-auto max-w-2xl px-4 sm:px-6 lg:max-w-7xl lg:px-8'>{children}</div>;
}
Dengan begitu, nantinya kita bisa menggunakan di beberapa komponen yang membutuhkannya termasuk dashboard kita. Teman-teman bisa buka file Dashboard.jsx
, kemudian silakan modifikasi isi dari dalamnya menjadi seperti:
import AppLayout from '@/Layouts/AppLayout';
import { Head } from '@inertiajs/react';
import Home from '@/Pages/Home';
import Container from '@/Components/Container';
export default function Dashboard({ auth }) {
return (
<>
<Head title='Dashboard' />
<div className='py-12'>
<Container>
<div className='overflow-hidden bg-white shadow-sm sm:rounded-lg'>
<div className='p-6 text-gray-900'>You're logged in!</div>
</div>
</Container>
</div>
</>
);
}
Dashboard.layout = (page) => (
<AppLayout
header={<h2 className='text-xl font-semibold leading-tight text-gray-800'>Dashboard</h2>}
children={page}
/>
);
Baik, sekarang pastikan bahwa teman-teman sudah menjalankan npm run dev
dan php artisan serve
. Dan sekarang silakan buka di browser, daftarkan akun baru, dan login. Maka teman-teman akan di arahkan ke halaman dashboard. Dan jika memang semua berjalan dengan baik, maka hasil akhir akan seperti ini:
π― Dashboard dan Home
Setelah itu, mari kita buat buat dua controller untuk halaman utama dan juga dashboard, silakan buka terminal dan jalankan perintah berikut:
php artisan make:controller HomeController -i
php artisan make:controller DashboardController -i
Setelah itu, silakan buka file routes/web.php
untuk membuat route dari keduanya, silakan modifikasi isinya menjadi seperti ini:
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\HomeController;
use App\Http\Controllers\ProfileController;
use Illuminate\Support\Facades\Route;
Route::get('/', HomeController::class)->name('home');
Route::get('dashboard', DashboardController::class)->middleware(['auth', 'verified'])->name('dashboard');
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';
Jika sudah, silakan buka file HomeController.php
dan silakan modifikasi isinya menjadi seperti ini:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
/**
* Handle the incoming request.
*/
public function __invoke(Request $request)
{
return inertia('Home');
}
}
Sebelum kita lanjut membuat view nya, mari kita langsung modifikasi apa yang ada di DashboardController.php
dan masukkan syntak berikut ini:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class DashboardController extends Controller
{
/**
* Handle the incoming request.
*/
public function __invoke(Request $request)
{
return inertia('Dashboard');
}
}
π₯ View untuk Home
Karena kita sudah memiliki view untuk dashboard, maka kita hanya akan membuat Home.jsx
pada folder resources/js/Pages
. Silakan buat file baru bernama Home.jsx
dan silakan masukkan syntak berikut:
import { Head } from '@inertiajs/react';
import AppLayout from '@/Layouts/AppLayout';
import Container from '@/Components/Container';
export default function Home({ products }) {
return (
<>
<Head title='Welcome to Online Store' />
<Container>
<div className='py-8 lg:py-16'>
<h2 className='text-2xl font-bold tracking-tight text-gray-900'>Trending Products</h2>
</div>
</Container>
</>
);
}
Home.layout = (page) => (
<AppLayout
header={<h2 className='text-xl font-semibold leading-tight text-gray-800'>Start Shopping</h2>}
children={page}
/>
);
Jika sudah, harusnya kita sudah ready untuk lanjut ke langkah berikutnya.