feat: UI cleanup
This commit is contained in:
parent
5c5ec88dfd
commit
6441a520a0
@ -11,7 +11,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
\Livewire\Livewire::forceAssetInjection();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -17,7 +17,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const HOME = '/home';
|
||||
public const HOME = '/dashboard';
|
||||
|
||||
/**
|
||||
* Define your route model bindings, pattern filters, and other route configuration.
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-red-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-red-500 active:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150']) }}>
|
||||
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-red-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-red-500 active:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 dark:focus:ring-offset-nexi-black transition ease-in-out duration-150']) }}>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
|
||||
22
resources/views/components/darkmode.blade.php
Normal file
22
resources/views/components/darkmode.blade.php
Normal file
@ -0,0 +1,22 @@
|
||||
<div class="flex items-center">
|
||||
<template x-if="darkMode === 'dark'">
|
||||
<button x-on:click="darkMode = 'light'" class="pl-6">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
x-bind:class="{'border-2 border-red/50': darkMode === 'light'}"
|
||||
class="w-6 h-6 p-1 text-gray-700 transition rounded-full cursor-pointer bg-gray-50 hover:bg-gray-200" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
|
||||
</svg>
|
||||
<span class="sr-only">light</span>
|
||||
</button>
|
||||
</template>
|
||||
<template x-if="darkMode !== 'dark'">
|
||||
<button x-on:click="darkMode = 'dark'" class="pl-6">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
x-bind:class="{'border-2 border-red/50': darkMode === 'dark'}"
|
||||
class="w-6 h-6 p-1 text-gray-100 transition bg-gray-700 rounded-full cursor-pointer dark:hover:bg-gray-600" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
|
||||
</svg>
|
||||
<span class="sr-only">dark</span>
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
@ -1 +1 @@
|
||||
<a {{ $attributes->merge(['class' => 'block w-full px-4 py-2 text-left text-sm leading-5 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-800 transition duration-150 ease-in-out']) }}>{{ $slot }}</a>
|
||||
<a {{ $attributes->merge(['class' => 'block w-full px-4 py-2 text-left text-sm leading-5 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-nexi-black focus:outline-none focus:bg-gray-100 dark:focus:bg-nexi-black transition duration-150 ease-in-out']) }}>{{ $slot }}</a>
|
||||
|
||||
@ -59,12 +59,12 @@ $maxWidth = [
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
>
|
||||
<div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
|
||||
<div class="absolute inset-0 bg-gray-500 dark:bg-nexi-black opacity-75"></div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
x-show="show"
|
||||
class="mb-6 bg-white dark:bg-gray-800 rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }} sm:mx-auto"
|
||||
class="mb-6 bg-white dark:bg-nexi-black rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }} sm:mx-auto"
|
||||
x-transition:enter="ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
@php
|
||||
$classes = ($active ?? false)
|
||||
? 'inline-flex items-center px-1 pt-1 border-b-2 border-nexi-red text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-nexi-red transition duration-150 ease-in-out'
|
||||
? 'inline-flex items-center px-1 pt-1 border-b-2 border-nexi-red text-sm font-medium leading-5 text-nexi-black focus:outline-none focus:border-nexi-red transition duration-150 ease-in-out'
|
||||
: 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-700 focus:outline-none focus:text-gray-700 dark:focus:text-gray-300 focus:border-gray-300 dark:focus:border-gray-700 transition duration-150 ease-in-out';
|
||||
@endphp
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
|
||||
@php
|
||||
$classes = ($active ?? false)
|
||||
? 'block w-full pl-3 pr-4 py-2 border-l-4 border-indigo-400 dark:border-indigo-600 text-left text-base font-medium text-indigo-700 dark:text-indigo-300 bg-indigo-50 dark:bg-indigo-900/50 focus:outline-none focus:text-indigo-800 dark:focus:text-indigo-200 focus:bg-indigo-100 dark:focus:bg-indigo-900 focus:border-indigo-700 dark:focus:border-indigo-300 transition duration-150 ease-in-out'
|
||||
: 'block w-full pl-3 pr-4 py-2 border-l-4 border-transparent text-left text-base font-medium text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 hover:border-gray-300 dark:hover:border-gray-600 focus:outline-none focus:text-gray-800 dark:focus:text-gray-200 focus:bg-gray-50 dark:focus:bg-gray-700 focus:border-gray-300 dark:focus:border-gray-600 transition duration-150 ease-in-out';
|
||||
? 'block w-full pl-3 pr-4 py-2 border-l-4 border-indigo-400 dark:border-indigo-600 text-left text-sm font-medium text-nexi-black dark:text-indigo-300 bg-indigo-50 dark:bg-indigo-900/50 focus:outline-none focus:text-indigo-800 dark:focus:text-indigo-200 focus:bg-indigo-100 dark:focus:bg-indigo-900 focus:border-indigo-700 dark:focus:border-indigo-300 transition duration-150 ease-in-out'
|
||||
: 'block w-full pl-3 pr-4 py-2 border-l-4 border-transparent text-left text-sm font-medium text-gray-600 dark:text-gray-400 hover:text-nexi-black dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 hover:border-gray-300 dark:hover:border-gray-600 focus:outline-none focus:text-nexi-black dark:focus:text-gray-200 focus:bg-gray-50 dark:focus:bg-gray-700 focus:border-gray-300 dark:focus:border-gray-600 transition duration-150 ease-in-out';
|
||||
@endphp
|
||||
|
||||
<a {{ $attributes->merge(['class' => $classes]) }}>
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
<button {{ $attributes->merge(['type' => 'button', 'class' => 'inline-flex items-center px-4 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-500 rounded-md font-semibold text-xs text-gray-700 dark:text-gray-300 uppercase tracking-widest shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 disabled:opacity-25 transition ease-in-out duration-150']) }}>
|
||||
<button {{ $attributes->merge(['type' => 'button', 'class' => 'inline-flex items-center px-4 py-2 bg-white dark:bg-nexi-black border border-gray-300 dark:border-gray-500 rounded-md font-semibold text-xs text-gray-700 dark:text-gray-300 uppercase tracking-widest shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-nexi-black disabled:opacity-25 transition ease-in-out duration-150']) }}>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
|
||||
8
resources/views/components/sidebar-nav.blade.php
Normal file
8
resources/views/components/sidebar-nav.blade.php
Normal file
@ -0,0 +1,8 @@
|
||||
@props(['route'])
|
||||
|
||||
<a {{ $attributes }} class="
|
||||
{{ Route::is($route)
|
||||
? 'text-nexi-red bg-gray-50 dark:text-nexi-purple dark:bg-zinc-800'
|
||||
: 'text-nexi-black dark:text-nexi-grey hover:text-nexi-red dark:hover:text-nexi-red hover:bg-gray-100 dark:hover:bg-zinc-500' }}
|
||||
group flex items-center px-2 py-2 text-base font-medium rounded-md"
|
||||
>{{ $slot }}</a>
|
||||
51
resources/views/components/sidebar.blade.php
Normal file
51
resources/views/components/sidebar.blade.php
Normal file
@ -0,0 +1,51 @@
|
||||
<div>
|
||||
<div class="flex h-16 shrink-0 items-center border-b border-gray-200">
|
||||
<a href="{{ route('dashboard') }}" wire:navigate>
|
||||
<img class="h-12 w-auto" src="https://benjamyn.love/PriceyBot.png" alt="">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<nav class="flex flex-1 flex-col">
|
||||
<ul role="list" class="flex flex-1 flex-col gap-y-7">
|
||||
<li class="border-b border-gray-200">
|
||||
<div class="text-xs font-semibold leading-6 text-gray-400">User Menu</div>
|
||||
<ul role="list" class="-mx-2 mt-2 space-y-1">
|
||||
<ul role="list" class="-mx-2 space-y-1">
|
||||
<li>
|
||||
{{-- TODO: fill with SVG icons to make it pretty --}}
|
||||
{{-- <svg class="h-6 w-6 shrink-0 text-indigo-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">--}}
|
||||
{{-- <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />--}}
|
||||
{{-- </svg>--}}
|
||||
<x-sidebar-nav :href="route('dashboard')" route="dashboard">First Page</x-sidebar-nav>
|
||||
</li>
|
||||
<li>
|
||||
{{-- TODO: fill with SVG icons to make it pretty --}}
|
||||
{{-- <x-sidebar-nav :href="route('u-2')" route="u-2">Second Page</x-sidebar-nav>--}}
|
||||
</li>
|
||||
<li>
|
||||
{{-- TODO: fill with SVG icons to make it pretty --}}
|
||||
{{-- <x-sidebar-nav :href="route('u-3')" route="u-3">Third Page</x-sidebar-nav>--}}
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<div class="text-xs font-semibold leading-6 text-gray-400">Admin Menu</div>
|
||||
<ul role="list" class="-mx-2 mt-2 space-y-1">
|
||||
<li>
|
||||
{{-- TODO: fill with SVG icons to make it pretty --}}
|
||||
{{-- <x-sidebar-nav :href="route('a-1')" route="a-1">First Page</x-sidebar-nav>--}}
|
||||
</li>
|
||||
<li>
|
||||
{{-- TODO: fill with SVG icons to make it pretty --}}
|
||||
{{-- <x-sidebar-nav :href="route('a-2')" route="a-2">Second Page</x-sidebar-nav>--}}
|
||||
</li>
|
||||
<li>
|
||||
{{-- TODO: fill with SVG icons to make it pretty --}}
|
||||
{{-- <x-sidebar-nav :href="route('a-3')" route="a-3">Third Page</x-sidebar-nav>--}}
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
@ -1,16 +1,8 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||
{{ __('Dashboard') }}
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
||||
<div class="p-6 text-gray-900 dark:text-gray-100">
|
||||
{{ __("You're logged in!") }}
|
||||
</div>
|
||||
<div class="p-6 text-nexi-black dark:text-gray-100">
|
||||
{{ __("You're logged in!") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"
|
||||
x-data="{
|
||||
darkMode: localStorage.getItem('darkMode') ||
|
||||
localStorage.setItem('darkMode', 'system')
|
||||
}"
|
||||
x-init="$watch('darkMode', val => localStorage.setItem('darkMode', val))"
|
||||
x-bind:class="{'dark': darkMode === 'dark' || (darkMode === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches)}"
|
||||
>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
@ -14,23 +21,67 @@
|
||||
<!-- Scripts -->
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
</head>
|
||||
<body class="font-sans antialiased">
|
||||
<div class="min-h-screen bg-gray-100 dark:bg-gray-900">
|
||||
<livewire:layout.navigation />
|
||||
<body class="antialiased bg-nexi-primary dark:bg-nexi-primary-dark font-sans text-nexi-black transition-colors duration-300">
|
||||
<div x-data="{ sidebarOpen: false }">
|
||||
<div class="relative z-50 lg:hidden" role="dialog" aria-modal="true">
|
||||
{{-- TODO: Look into why the fuck does this not work? mobile views seem to not work with livewire clicks??? --}}
|
||||
<div x-show="sidebarOpen"
|
||||
x-transition:enter="transition-opacity ease-linear duration-300"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="transition-opacity ease-linear duration-300"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
class="fixed inset-0 bg-nexi-black/80"></div>
|
||||
|
||||
<!-- Page Heading -->
|
||||
@if (isset($header))
|
||||
<header class="bg-white dark:bg-gray-800 shadow">
|
||||
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
{{ $header }}
|
||||
<div class="fixed inset-0 flex">
|
||||
<div x-show="sidebarOpen"
|
||||
x-transition:enter="transition ease-in-out duration-300 transform"
|
||||
x-transition:enter-start="-translate-x-full"
|
||||
x-transition:enter-end="translate-x-0"
|
||||
x-transition:leave="transition ease-in-out duration-300 transform"
|
||||
x-transition:leave-start="translate-x-0"
|
||||
x-transition:leave-end="-translate-x-full"
|
||||
class="relative mr-16 flex w-full max-w-xs flex-1">
|
||||
|
||||
<div x-show="sidebarOpen"
|
||||
x-transition:enter="ease-in-out duration-300"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="ease-in-out duration-300"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
class="absolute left-full top-0 flex w-16 justify-center pt-5">
|
||||
<button type="button" class="-m-2.5 p-2.5" @click="sidebarOpen = false">
|
||||
<svg class="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex grow flex-col gap-y-5 overflow-y-auto px-6 pb-4">
|
||||
<x-sidebar/>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
{{ $slot }}
|
||||
</main>
|
||||
<!-- Static sidebar for desktop -->
|
||||
<div class="hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:w-72 lg:flex-col">
|
||||
<div class="flex grow flex-col gap-y-5 overflow-y-auto border-r border-gray-200 px-6 pb-4">
|
||||
<x-sidebar/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="lg:pl-72">
|
||||
<livewire:layout.navigation />
|
||||
|
||||
<main class="py-10">
|
||||
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
<!-- Scripts -->
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
</head>
|
||||
<body class="antialiased bg-nexi-primary dark:bg-nexi-primary-dark font-sans text-gray-900">
|
||||
<body class="antialiased bg-nexi-primary dark:bg-nexi-primary-dark font-sans text-nexi-black transition-colors duration-300">
|
||||
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 ">
|
||||
{{-- TODO: REPLACE WITH OUR LOGO --}}
|
||||
<div>
|
||||
|
||||
@ -1,35 +1,20 @@
|
||||
<div class="sm:fixed sm:top-0 sm:right-0 p-6 text-right z-10">
|
||||
<div class="sm:fixed sm:top-0 sm:right-0 p-6 text-right z-10 bg-nexi-primary dark:bg-nexi-primary-dark transition-colors duration-300">
|
||||
@auth
|
||||
<a href="{{ url('/home') }}"
|
||||
class="font-semibold text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-red-500"
|
||||
wire:navigate
|
||||
>Dashboard</a>
|
||||
<div class="pr-6 flex">
|
||||
<a href="{{ url('/dashboard') }}"
|
||||
class="font-semibold text-gray-600 hover:text-nexi-black dark:text-gray-400 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-red-500"
|
||||
wire:navigate
|
||||
>Dashboard</a>
|
||||
|
||||
<x-darkmode/>
|
||||
</div>
|
||||
@else
|
||||
<div class="pr-6">
|
||||
<div class="pr-6 flex">
|
||||
<a href="{{ route('login') }}"
|
||||
class="font-semibold text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-red-500"
|
||||
class="font-semibold text-gray-600 hover:text-nexi-black dark:text-gray-400 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-red-500"
|
||||
wire:navigate>Log in</a>
|
||||
|
||||
<template x-if="darkMode === 'dark'">
|
||||
<button x-on:click="darkMode = 'light'" class="pl-6">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
x-bind:class="{'border-2 border-red/50': darkMode === 'light'}"
|
||||
class="w-6 h-6 p-1 text-gray-700 transition rounded-full cursor-pointer bg-gray-50 hover:bg-gray-200" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
|
||||
</svg>
|
||||
<span class="sr-only">light</span>
|
||||
</button>
|
||||
</template>
|
||||
<template x-if="darkMode !== 'dark'">
|
||||
<button x-on:click="darkMode = 'dark'" class="pl-6">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
x-bind:class="{'border-2 border-red/50': darkMode === 'dark'}"
|
||||
class="w-6 h-6 p-1 text-gray-100 transition bg-gray-700 rounded-full cursor-pointer dark:hover:bg-gray-600" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
|
||||
</svg>
|
||||
<span class="sr-only">dark</span>
|
||||
</button>
|
||||
</template>
|
||||
<x-darkmode/>
|
||||
</div>
|
||||
@endauth
|
||||
</div>
|
||||
|
||||
@ -15,94 +15,70 @@ new class extends Component
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<nav x-data="{ open: false }" class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700">
|
||||
<!-- Primary Navigation Menu -->
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between h-16">
|
||||
<div class="flex">
|
||||
<!-- Logo -->
|
||||
<div class="shrink-0 flex items-center">
|
||||
<a href="{{ route('dashboard') }}" wire:navigate>
|
||||
<x-application-logo class="block h-9 w-auto fill-current text-gray-800 dark:text-gray-200" />
|
||||
</a>
|
||||
<nav x-data="{ openProfile : false }" class="sticky top-0 z-40 lg:mx-auto lg:max-w-7xl lg:px-8 bg-nexi-primary dark:bg-nexi-primary-dark transition-colors duration-300">
|
||||
<div class="flex h-16 items-center gap-x-4 border-b border-gray-200 px-4 shadow-sm sm:gap-x-6 sm:px-6 lg:px-0 lg:shadow-none">
|
||||
<button type="button" class="-m-2.5 p-2.5 text-gray-700 lg:hidden" @click="sidebarOpen = true">
|
||||
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Separator -->
|
||||
<div class="h-6 w-px bg-gray-200 lg:hidden" aria-hidden="true"></div>
|
||||
|
||||
<div class="flex flex-1 gap-x-4 self-stretch lg:gap-x-6 flex-row-reverse">
|
||||
|
||||
<div class="flex items-center gap-x-4 lg:gap-x-6">
|
||||
{{-- TODO: Hide this on mobile and put in under user menu? maybe move to side bar--}}
|
||||
<x-darkmode/>
|
||||
|
||||
<!-- Separator -->
|
||||
<div class="hidden lg:block lg:h-6 lg:w-px lg:bg-gray-200" aria-hidden="true"></div>
|
||||
|
||||
<!-- Profile dropdown -->
|
||||
<div class="relative">
|
||||
<button @click="openProfile = ! openProfile"
|
||||
type="button"
|
||||
class="-m-1.5 flex items-center p-1.5"
|
||||
id="user-menu-button"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true">
|
||||
{{-- TODO: Add User Image URL here --}}
|
||||
<img class="h-8 w-8 rounded-full bg-gray-50" src="" alt="">
|
||||
<span class="hidden lg:flex lg:items-center">
|
||||
<span class="ml-4 text-base font-semibold leading-6 text-nexi-black dark:text-nexi-grey" aria-hidden="true" x-data="{ name: '{{ auth()->user()->name }}' }" x-text="name" x-on:profile-updated.window="name = $event.detail.name"></span>
|
||||
<svg class="ml-2 h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<div class="absolute right-0 z-10 mt-2.5 w-32 origin-top-right rounded-md bg-nexi-primary dark:bg-nexi-primary-dark py-2 shadow-lg ring-1 ring-nexi-black/5 dark:ring-nexi-grey focus:outline-none"
|
||||
role="menu"
|
||||
aria-orientation="vertical"
|
||||
aria-labelledby="user-menu-button"
|
||||
tabindex="-1"
|
||||
x-show="openProfile"
|
||||
x-transition:enter="transition ease-out duration-100 transform opacity-0 scale-95"
|
||||
x-transition:enter-start="transform opacity-0 scale-95"
|
||||
x-transition:enter-end="transform opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-75 transform opacity-100 scale-100"
|
||||
x-transition:leave-start="transform opacity-100 scale-100"
|
||||
x-transition:leave-end="transform opacity-0 scale-95"
|
||||
>
|
||||
<div class="mt-3 space-y-1 text-sm">
|
||||
<x-responsive-nav-link u :href="route('profile')" wire:navigate>
|
||||
{{ __('Profile') }}
|
||||
</x-responsive-nav-link>
|
||||
|
||||
<button wire:click="logout" class="w-full text-left">
|
||||
<x-responsive-nav-link>
|
||||
{{ __('Log Out') }}
|
||||
</x-responsive-nav-link>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation Links -->
|
||||
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
|
||||
<x-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')" wire:navigate>
|
||||
{{ __('Dashboard') }}
|
||||
</x-nav-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Settings Dropdown -->
|
||||
<div class="hidden sm:flex sm:items-center sm:ml-6">
|
||||
<x-dropdown align="right" width="48">
|
||||
<x-slot name="trigger">
|
||||
<button class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150">
|
||||
<div x-data="{ name: '{{ auth()->user()->name }}' }" x-text="name" x-on:profile-updated.window="name = $event.detail.name"></div>
|
||||
|
||||
<div class="ml-1">
|
||||
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
|
||||
<path fill-rule="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" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
<x-dropdown-link :href="route('profile')" wire:navigate>
|
||||
{{ __('Profile') }}
|
||||
</x-dropdown-link>
|
||||
|
||||
<!-- Authentication -->
|
||||
<button wire:click="logout" class="w-full text-left">
|
||||
<x-dropdown-link>
|
||||
{{ __('Log Out') }}
|
||||
</x-dropdown-link>
|
||||
</button>
|
||||
</x-slot>
|
||||
</x-dropdown>
|
||||
</div>
|
||||
|
||||
<!-- Hamburger -->
|
||||
<div class="-mr-2 flex items-center sm:hidden">
|
||||
<button @click="open = ! open" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-900 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-900 focus:text-gray-500 dark:focus:text-gray-400 transition duration-150 ease-in-out">
|
||||
<svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||
<path :class="{'hidden': open, 'inline-flex': ! open }" class="inline-flex" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
<path :class="{'hidden': ! open, 'inline-flex': open }" class="hidden" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Responsive Navigation Menu -->
|
||||
<div :class="{'block': open, 'hidden': ! open}" class="hidden sm:hidden">
|
||||
<div class="pt-2 pb-3 space-y-1">
|
||||
<x-responsive-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')" wire:navigate>
|
||||
{{ __('Dashboard') }}
|
||||
</x-responsive-nav-link>
|
||||
</div>
|
||||
|
||||
<!-- Responsive Settings Options -->
|
||||
<div class="pt-4 pb-1 border-t border-gray-200 dark:border-gray-600">
|
||||
<div class="px-4">
|
||||
<div class="font-medium text-base text-gray-800 dark:text-gray-200" x-data="{ name: '{{ auth()->user()->name }}' }" x-text="name" x-on:profile-updated.window="name = $event.detail.name"></div>
|
||||
<div class="font-medium text-sm text-gray-500">{{ auth()->user()->email }}</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 space-y-1">
|
||||
<x-responsive-nav-link :href="route('profile')" wire:navigate>
|
||||
{{ __('Profile') }}
|
||||
</x-responsive-nav-link>
|
||||
|
||||
<!-- Authentication -->
|
||||
<button wire:click="logout" class="w-full text-left">
|
||||
<x-responsive-nav-link>
|
||||
{{ __('Log Out') }}
|
||||
</x-responsive-nav-link>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -26,6 +26,7 @@ new #[Layout('layouts.guest')] class extends Component
|
||||
|
||||
$this->ensureIsNotRateLimited();
|
||||
|
||||
|
||||
if (!auth()->attempt($this->only(['email', 'password'], $this->remember))) {
|
||||
RateLimiter::hit($this->throttleKey());
|
||||
|
||||
@ -113,7 +114,7 @@ new #[Layout('layouts.guest')] class extends Component
|
||||
|
||||
<div class="flex items-center justify-end mt-4">
|
||||
@if (Route::has('password.request'))
|
||||
<a class="underline text-sm text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-nexi-red"
|
||||
<a class="underline text-sm text-gray-600 dark:text-gray-300 hover:text-nexi-black dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-nexi-red"
|
||||
href="{{ route('password.request') }}"
|
||||
wire:navigate>
|
||||
{{ __('Forgot your password?') }}
|
||||
|
||||
@ -23,7 +23,7 @@ new class extends Component
|
||||
|
||||
<section class="space-y-6">
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
<h2 class="text-lg font-medium text-nexi-black dark:text-gray-100">
|
||||
{{ __('Delete Account') }}
|
||||
</h2>
|
||||
|
||||
@ -40,7 +40,7 @@ new class extends Component
|
||||
<x-modal name="confirm-user-deletion" :show="$errors->isNotEmpty()" focusable>
|
||||
<form wire:submit="deleteUser" class="p-6">
|
||||
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
<h2 class="text-lg font-medium text-nexi-black dark:text-gray-100">
|
||||
{{ __('Are you sure you want to delete your account?') }}
|
||||
</h2>
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ new class extends Component
|
||||
|
||||
<section>
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
<h2 class="text-lg font-medium text-nexi-black dark:text-gray-100">
|
||||
{{ __('Update Password') }}
|
||||
</h2>
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ new class extends Component
|
||||
|
||||
<section>
|
||||
<header>
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
<h2 class="text-lg font-medium text-nexi-black dark:text-gray-100">
|
||||
{{ __('Profile Information') }}
|
||||
</h2>
|
||||
|
||||
@ -80,10 +80,10 @@ new class extends Component
|
||||
|
||||
@if (auth()->user() instanceof MustVerifyEmail && ! auth()->user()->hasVerifiedEmail())
|
||||
<div>
|
||||
<p class="text-sm mt-2 text-gray-800 dark:text-gray-200">
|
||||
<p class="text-sm mt-2 text-nexi-black dark:text-gray-200">
|
||||
{{ __('Your email address is unverified.') }}
|
||||
|
||||
<button wire:click.prevent="sendVerification" class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800">
|
||||
<button wire:click.prevent="sendVerification" class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-nexi-black dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-nexi-black">
|
||||
{{ __('Click here to re-send the verification email.') }}
|
||||
</button>
|
||||
</p>
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||
<h2 class="font-semibold text-xl text-nexi-black dark:text-gray-200 leading-tight">
|
||||
{{ __('Profile') }}
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="p-4 sm:p-8 shadow sm:rounded-lg dark:shadow-zinc-600">
|
||||
<div class="max-w-xl">
|
||||
<livewire:profile.update-profile-information-form />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="p-4 sm:p-8 shadow sm:rounded-lg dark:shadow-zinc-600">
|
||||
<div class="max-w-xl">
|
||||
<livewire:profile.update-password-form />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
|
||||
<div class="p-4 sm:p-8 shadow sm:rounded-lg dark:shadow-zinc-600">
|
||||
<div class="max-w-xl">
|
||||
<livewire:profile.delete-user-form />
|
||||
</div>
|
||||
|
||||
@ -39,6 +39,7 @@ export default {
|
||||
'nexi-red': "rgb( 235, 49, 46)",
|
||||
'nexi-grey': "rgb(228, 228, 228)",
|
||||
'nexi-darker-grey': "rgb(210, 210, 210)",
|
||||
'nexi-dark-grey': "rgb(98,98,98)",
|
||||
'nexi-green': "rgb(54, 234, 123)",
|
||||
'nexi-cyan': "rgb(54, 233, 234)",
|
||||
'nexi-purple': "rgb(166, 37, 234)",
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Auth\Events\Verified;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
|
||||
test('email verification screen can be rendered', function () {
|
||||
$user = User::factory()->create([
|
||||
'email_verified_at' => null,
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)->get('/verify-email');
|
||||
|
||||
$response->assertStatus(200);
|
||||
});
|
||||
|
||||
test('email can be verified', function () {
|
||||
$user = User::factory()->create([
|
||||
'email_verified_at' => null,
|
||||
]);
|
||||
|
||||
Event::fake();
|
||||
|
||||
$verificationUrl = URL::temporarySignedRoute(
|
||||
'verification.verify',
|
||||
now()->addMinutes(60),
|
||||
['id' => $user->id, 'hash' => sha1($user->email)]
|
||||
);
|
||||
|
||||
$response = $this->actingAs($user)->get($verificationUrl);
|
||||
|
||||
Event::assertDispatched(Verified::class);
|
||||
expect($user->fresh()->hasVerifiedEmail())->toBeTrue();
|
||||
$response->assertRedirect(RouteServiceProvider::HOME.'?verified=1');
|
||||
});
|
||||
|
||||
test('email is not verified with invalid hash', function () {
|
||||
$user = User::factory()->create([
|
||||
'email_verified_at' => null,
|
||||
]);
|
||||
|
||||
$verificationUrl = URL::temporarySignedRoute(
|
||||
'verification.verify',
|
||||
now()->addMinutes(60),
|
||||
['id' => $user->id, 'hash' => sha1('wrong-email')]
|
||||
);
|
||||
|
||||
$this->actingAs($user)->get($verificationUrl);
|
||||
|
||||
expect($user->fresh()->hasVerifiedEmail())->toBeFalse();
|
||||
});
|
||||
Reference in New Issue
Block a user