@mamut_1945/dashboard-ui 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -10
- package/resources/views/components/common/common-grid-shape.blade.php +8 -0
- package/resources/views/components/common/component-card.blade.php +25 -0
- package/resources/views/components/common/dropdown-menu.blade.php +22 -0
- package/resources/views/components/common/form.blade.php +21 -0
- package/resources/views/components/common/input-group.blade.php +100 -0
- package/resources/views/components/common/page-breadcrumb.blade.php +38 -0
- package/resources/views/components/common/preloader.blade.php +9 -0
- package/resources/views/components/common/table.blade.php +73 -0
- package/resources/views/components/common/theme-toggle.blade.php +30 -0
- package/resources/views/components/header/user-dropdown.blade.php +128 -0
- package/resources/views/components/readme.txt +6 -0
- package/resources/views/components/ui/alert.blade.php +82 -0
- package/resources/views/components/ui/avatar.blade.php +49 -0
- package/resources/views/components/ui/badge.blade.php +53 -0
- package/resources/views/components/ui/button.blade.php +61 -0
- package/resources/views/components/ui/modal.blade.php +59 -0
- package/resources/views/components/ui/youtube-embed.blade.php +29 -0
- package/resources/views/layouts/app-header.blade.php +96 -0
- package/resources/views/layouts/app.blade.php +138 -0
- package/resources/views/layouts/backdrop.blade.php +12 -0
- package/resources/views/layouts/fullscreen-layout.blade.php +117 -0
- package/resources/views/layouts/sidebar.blade.php +225 -0
- package/resources/views/pages/example/easy-form-example.blade.php +40 -0
- package/resources/views/pages/example/table-example.blade.php +45 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
|
|
2
|
+
@php
|
|
3
|
+
use App\Helpers\MenuHelper;
|
|
4
|
+
$menuGroups = MenuHelper::getMenuGroups();
|
|
5
|
+
|
|
6
|
+
// Get current path
|
|
7
|
+
$currentPath = request()->path();
|
|
8
|
+
@endphp
|
|
9
|
+
|
|
10
|
+
<aside id="sidebar"
|
|
11
|
+
class="fixed flex flex-col mt-0 top-0 px-5 left-0 bg-white dark:bg-gray-900 dark:border-gray-800 text-gray-900 h-screen transition-all duration-300 ease-in-out z-99999 border-r border-gray-200"
|
|
12
|
+
x-data="{
|
|
13
|
+
openSubmenus: {},
|
|
14
|
+
init() {
|
|
15
|
+
// Auto-open Dashboard menu on page load
|
|
16
|
+
this.initializeActiveMenus();
|
|
17
|
+
},
|
|
18
|
+
initializeActiveMenus() {
|
|
19
|
+
const currentPath = '{{ $currentPath }}';
|
|
20
|
+
|
|
21
|
+
@foreach ($menuGroups as $groupIndex => $menuGroup)
|
|
22
|
+
@foreach ($menuGroup['items'] as $itemIndex => $item)
|
|
23
|
+
@if (isset($item['subItems']))
|
|
24
|
+
// Check if any submenu item matches current path
|
|
25
|
+
@foreach ($item['subItems'] as $subItem)
|
|
26
|
+
if (currentPath === '{{ ltrim($subItem['path'], '/') }}' ||
|
|
27
|
+
window.location.pathname === '{{ $subItem['path'] }}') {
|
|
28
|
+
this.openSubmenus['{{ $groupIndex }}-{{ $itemIndex }}'] = true;
|
|
29
|
+
} @endforeach
|
|
30
|
+
@endif
|
|
31
|
+
@endforeach
|
|
32
|
+
@endforeach
|
|
33
|
+
},
|
|
34
|
+
toggleSubmenu(groupIndex, itemIndex) {
|
|
35
|
+
const key = groupIndex + '-' + itemIndex;
|
|
36
|
+
const newState = !this.openSubmenus[key];
|
|
37
|
+
|
|
38
|
+
// Close all other submenus when opening a new one
|
|
39
|
+
if (newState) {
|
|
40
|
+
this.openSubmenus = {};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
this.openSubmenus[key] = newState;
|
|
44
|
+
},
|
|
45
|
+
isSubmenuOpen(groupIndex, itemIndex) {
|
|
46
|
+
const key = groupIndex + '-' + itemIndex;
|
|
47
|
+
return this.openSubmenus[key] || false;
|
|
48
|
+
},
|
|
49
|
+
isActive(path) {
|
|
50
|
+
return window.location.pathname === path || '{{ $currentPath }}' === path.replace(/^\//, '');
|
|
51
|
+
}
|
|
52
|
+
}"
|
|
53
|
+
:class="{
|
|
54
|
+
'w-[290px]': $store.sidebar.isExpanded || $store.sidebar.isMobileOpen || $store.sidebar.isHovered,
|
|
55
|
+
'w-[90px]': !$store.sidebar.isExpanded && !$store.sidebar.isHovered,
|
|
56
|
+
'translate-x-0': $store.sidebar.isMobileOpen,
|
|
57
|
+
'-translate-x-full xl:translate-x-0': !$store.sidebar.isMobileOpen
|
|
58
|
+
}"
|
|
59
|
+
@mouseenter="if (!$store.sidebar.isExpanded) $store.sidebar.setHovered(true)"
|
|
60
|
+
@mouseleave="$store.sidebar.setHovered(false)">
|
|
61
|
+
<!-- Logo Section -->
|
|
62
|
+
<div class="pt-8 pb-7 flex"
|
|
63
|
+
:class="(!$store.sidebar.isExpanded && !$store.sidebar.isHovered && !$store.sidebar.isMobileOpen) ?
|
|
64
|
+
'xl:justify-center' :
|
|
65
|
+
'justify-start'">
|
|
66
|
+
<a href="/">
|
|
67
|
+
<img x-show="$store.sidebar.isExpanded || $store.sidebar.isHovered || $store.sidebar.isMobileOpen"
|
|
68
|
+
class="dark:hidden" src="/images/logo/logo.svg" alt="Logo" width="150" height="40" />
|
|
69
|
+
<img x-show="$store.sidebar.isExpanded || $store.sidebar.isHovered || $store.sidebar.isMobileOpen"
|
|
70
|
+
class="hidden dark:block" src="/images/logo/logo-dark.svg" alt="Logo" width="150"
|
|
71
|
+
height="40" />
|
|
72
|
+
<img x-show="!$store.sidebar.isExpanded && !$store.sidebar.isHovered && !$store.sidebar.isMobileOpen"
|
|
73
|
+
src="/images/logo/logo-icon.svg" alt="Logo" width="32" height="32" />
|
|
74
|
+
|
|
75
|
+
</a>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<!-- Navigation Menu -->
|
|
79
|
+
<div class="flex flex-col overflow-y-auto duration-300 ease-linear no-scrollbar">
|
|
80
|
+
<nav class="mb-6">
|
|
81
|
+
<div class="flex flex-col gap-4">
|
|
82
|
+
@foreach ($menuGroups as $groupIndex => $menuGroup)
|
|
83
|
+
<div>
|
|
84
|
+
<!-- Menu Group Title -->
|
|
85
|
+
<h2 class="mb-4 text-xs uppercase flex leading-[20px] text-gray-400"
|
|
86
|
+
:class="(!$store.sidebar.isExpanded && !$store.sidebar.isHovered && !$store.sidebar.isMobileOpen) ?
|
|
87
|
+
'lg:justify-center' : 'justify-start'">
|
|
88
|
+
<template
|
|
89
|
+
x-if="$store.sidebar.isExpanded || $store.sidebar.isHovered || $store.sidebar.isMobileOpen">
|
|
90
|
+
<span>{{ $menuGroup['title'] }}</span>
|
|
91
|
+
</template>
|
|
92
|
+
<template x-if="!$store.sidebar.isExpanded && !$store.sidebar.isHovered && !$store.sidebar.isMobileOpen">
|
|
93
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
94
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.99915 10.2451C6.96564 10.2451 7.74915 11.0286 7.74915 11.9951V12.0051C7.74915 12.9716 6.96564 13.7551 5.99915 13.7551C5.03265 13.7551 4.24915 12.9716 4.24915 12.0051V11.9951C4.24915 11.0286 5.03265 10.2451 5.99915 10.2451ZM17.9991 10.2451C18.9656 10.2451 19.7491 11.0286 19.7491 11.9951V12.0051C19.7491 12.9716 18.9656 13.7551 17.9991 13.7551C17.0326 13.7551 16.2491 12.9716 16.2491 12.0051V11.9951C16.2491 11.0286 17.0326 10.2451 17.9991 10.2451ZM13.7491 11.9951C13.7491 11.0286 12.9656 10.2451 11.9991 10.2451C11.0326 10.2451 10.2491 11.0286 10.2491 11.9951V12.0051C10.2491 12.9716 11.0326 13.7551 11.9991 13.7551C12.9656 13.7551 13.7491 12.9716 13.7491 12.0051V11.9951Z" fill="currentColor"/>
|
|
95
|
+
</svg>
|
|
96
|
+
</template>
|
|
97
|
+
</h2>
|
|
98
|
+
|
|
99
|
+
<!-- Menu Items -->
|
|
100
|
+
<ul class="flex flex-col gap-1">
|
|
101
|
+
@foreach ($menuGroup['items'] as $itemIndex => $item)
|
|
102
|
+
<li>
|
|
103
|
+
@if (isset($item['subItems']))
|
|
104
|
+
<!-- Menu Item with Submenu -->
|
|
105
|
+
<button @click="toggleSubmenu({{ $groupIndex }}, {{ $itemIndex }})"
|
|
106
|
+
class="menu-item group w-full"
|
|
107
|
+
:class="[
|
|
108
|
+
isSubmenuOpen({{ $groupIndex }}, {{ $itemIndex }}) ?
|
|
109
|
+
'menu-item-active' : 'menu-item-inactive',
|
|
110
|
+
!$store.sidebar.isExpanded && !$store.sidebar.isHovered ?
|
|
111
|
+
'xl:justify-center' : 'xl:justify-start'
|
|
112
|
+
]">
|
|
113
|
+
|
|
114
|
+
<!-- Icon -->
|
|
115
|
+
<span :class="isSubmenuOpen({{ $groupIndex }}, {{ $itemIndex }}) ?
|
|
116
|
+
'menu-item-icon-active' : 'menu-item-icon-inactive'">
|
|
117
|
+
{!! MenuHelper::getIconSvg($item['icon']) !!}
|
|
118
|
+
</span>
|
|
119
|
+
|
|
120
|
+
<!-- Text -->
|
|
121
|
+
<span
|
|
122
|
+
x-show="$store.sidebar.isExpanded || $store.sidebar.isHovered || $store.sidebar.isMobileOpen"
|
|
123
|
+
class="menu-item-text flex items-center gap-2">
|
|
124
|
+
{{ $item['name'] }}
|
|
125
|
+
@if (!empty($item['new']))
|
|
126
|
+
<span class="absolute right-10"
|
|
127
|
+
:class="isActive('{{ $item['path'] ?? '' }}') ?
|
|
128
|
+
'menu-dropdown-badge menu-dropdown-badge-active' :
|
|
129
|
+
'menu-dropdown-badge menu-dropdown-badge-inactive'">
|
|
130
|
+
new
|
|
131
|
+
</span>
|
|
132
|
+
@endif
|
|
133
|
+
</span>
|
|
134
|
+
|
|
135
|
+
<!-- Chevron Down Icon -->
|
|
136
|
+
<svg x-show="$store.sidebar.isExpanded || $store.sidebar.isHovered || $store.sidebar.isMobileOpen"
|
|
137
|
+
class="ml-auto w-5 h-5 transition-transform duration-200"
|
|
138
|
+
:class="{
|
|
139
|
+
'rotate-180 text-brand-500': isSubmenuOpen({{ $groupIndex }},
|
|
140
|
+
{{ $itemIndex }})
|
|
141
|
+
}"
|
|
142
|
+
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
143
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
|
144
|
+
</svg>
|
|
145
|
+
</button>
|
|
146
|
+
|
|
147
|
+
<!-- Submenu -->
|
|
148
|
+
<div x-show="isSubmenuOpen({{ $groupIndex }}, {{ $itemIndex }}) && ($store.sidebar.isExpanded || $store.sidebar.isHovered || $store.sidebar.isMobileOpen)">
|
|
149
|
+
<ul class="mt-2 space-y-1 ml-9">
|
|
150
|
+
@foreach ($item['subItems'] as $subItem)
|
|
151
|
+
<li>
|
|
152
|
+
<a href="{{ $subItem['path'] }}" class="menu-dropdown-item"
|
|
153
|
+
:class="isActive('{{ $subItem['path'] }}') ?
|
|
154
|
+
'menu-dropdown-item-active' :
|
|
155
|
+
'menu-dropdown-item-inactive'">
|
|
156
|
+
{{ $subItem['name'] }}
|
|
157
|
+
<span class="flex items-center gap-1 ml-auto">
|
|
158
|
+
@if (!empty($subItem['new']))
|
|
159
|
+
<span
|
|
160
|
+
:class="isActive('{{ $subItem['path'] }}') ?
|
|
161
|
+
'menu-dropdown-badge menu-dropdown-badge-active' :
|
|
162
|
+
'menu-dropdown-badge menu-dropdown-badge-inactive'">
|
|
163
|
+
new
|
|
164
|
+
</span>
|
|
165
|
+
@endif
|
|
166
|
+
@if (!empty($subItem['pro']))
|
|
167
|
+
<span
|
|
168
|
+
:class="isActive('{{ $subItem['path'] }}') ?
|
|
169
|
+
'menu-dropdown-badge-pro menu-dropdown-badge-pro-active' :
|
|
170
|
+
'menu-dropdown-badge-pro menu-dropdown-badge-pro-inactive'">
|
|
171
|
+
pro
|
|
172
|
+
</span>
|
|
173
|
+
@endif
|
|
174
|
+
</span>
|
|
175
|
+
</a>
|
|
176
|
+
</li>
|
|
177
|
+
@endforeach
|
|
178
|
+
</ul>
|
|
179
|
+
</div>
|
|
180
|
+
@else
|
|
181
|
+
<!-- Simple Menu Item -->
|
|
182
|
+
<a href="{{ $item['path'] }}" class="menu-item group"
|
|
183
|
+
:class="[
|
|
184
|
+
isActive('{{ $item['path'] }}') ? 'menu-item-active' :
|
|
185
|
+
'menu-item-inactive',
|
|
186
|
+
(!$store.sidebar.isExpanded && !$store.sidebar.isHovered && !$store.sidebar.isMobileOpen) ?
|
|
187
|
+
'xl:justify-center' :
|
|
188
|
+
'justify-start'
|
|
189
|
+
]">
|
|
190
|
+
|
|
191
|
+
<!-- Icon -->
|
|
192
|
+
<span
|
|
193
|
+
:class="isActive('{{ $item['path'] }}') ? 'menu-item-icon-active' :
|
|
194
|
+
'menu-item-icon-inactive'">
|
|
195
|
+
{!! MenuHelper::getIconSvg($item['icon']) !!}
|
|
196
|
+
</span>
|
|
197
|
+
|
|
198
|
+
<!-- Text -->
|
|
199
|
+
<span
|
|
200
|
+
x-show="$store.sidebar.isExpanded || $store.sidebar.isHovered || $store.sidebar.isMobileOpen"
|
|
201
|
+
class="menu-item-text flex items-center gap-2">
|
|
202
|
+
{{ $item['name'] }}
|
|
203
|
+
@if (!empty($item['new']))
|
|
204
|
+
<span
|
|
205
|
+
class="ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-semibold bg-brand-500 text-white">
|
|
206
|
+
new
|
|
207
|
+
</span>
|
|
208
|
+
@endif
|
|
209
|
+
</span>
|
|
210
|
+
</a>
|
|
211
|
+
@endif
|
|
212
|
+
</li>
|
|
213
|
+
@endforeach
|
|
214
|
+
</ul>
|
|
215
|
+
</div>
|
|
216
|
+
@endforeach
|
|
217
|
+
</div>
|
|
218
|
+
</nav>
|
|
219
|
+
|
|
220
|
+
</div>
|
|
221
|
+
</aside>
|
|
222
|
+
|
|
223
|
+
<!-- Mobile Overlay -->
|
|
224
|
+
<div x-show="$store.sidebar.isMobileOpen" @click="$store.sidebar.setMobileOpen(false)"
|
|
225
|
+
class="fixed z-50 h-screen w-full bg-gray-900/50"></div>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
@extends('layouts.app')
|
|
2
|
+
|
|
3
|
+
@section('content')
|
|
4
|
+
<x-common.component-card title="Input Group">
|
|
5
|
+
<x-common.form
|
|
6
|
+
action=""
|
|
7
|
+
method=""
|
|
8
|
+
:fields="[
|
|
9
|
+
[
|
|
10
|
+
'type' => 'name',
|
|
11
|
+
'label' => 'Name',
|
|
12
|
+
'name' => 'name',
|
|
13
|
+
'placeholder' => 'Enter your name',
|
|
14
|
+
],
|
|
15
|
+
[
|
|
16
|
+
'type' => 'email',
|
|
17
|
+
'label' => 'Email',
|
|
18
|
+
'name' => 'email',
|
|
19
|
+
'placeholder' => 'example@gmail.com',
|
|
20
|
+
],
|
|
21
|
+
[
|
|
22
|
+
'type' => 'select',
|
|
23
|
+
'label' => 'Role',
|
|
24
|
+
'name' => 'role',
|
|
25
|
+
'options' => [
|
|
26
|
+
'admin' => 'Admin',
|
|
27
|
+
'user' => 'User',
|
|
28
|
+
],
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
'type' => 'password',
|
|
32
|
+
'label' => 'password',
|
|
33
|
+
'name' => 'password',
|
|
34
|
+
'placeholder' => 'Enter your password',
|
|
35
|
+
],
|
|
36
|
+
]"
|
|
37
|
+
/>
|
|
38
|
+
</x-common.component-card>
|
|
39
|
+
|
|
40
|
+
@endsection
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
@extends('layouts.app')
|
|
2
|
+
|
|
3
|
+
@section('content')
|
|
4
|
+
<x-common.component-card title="Input Group">
|
|
5
|
+
<x-common.table
|
|
6
|
+
title="Recent Orders"
|
|
7
|
+
:headers="[
|
|
8
|
+
'Product / Service',
|
|
9
|
+
'Deal Value',
|
|
10
|
+
'Close Date',
|
|
11
|
+
'Status',
|
|
12
|
+
]"
|
|
13
|
+
:rows="[
|
|
14
|
+
[
|
|
15
|
+
'product' => 'Website Company',
|
|
16
|
+
'price' => 'Rp 5.000.000',
|
|
17
|
+
'date' => '2026-02-01',
|
|
18
|
+
'status' => 'paid',
|
|
19
|
+
],
|
|
20
|
+
[
|
|
21
|
+
'product' => 'Mobile App',
|
|
22
|
+
'price' => 'Rp 8.000.000',
|
|
23
|
+
'date' => '2026-02-05',
|
|
24
|
+
'status' => 'pending',
|
|
25
|
+
],
|
|
26
|
+
]"
|
|
27
|
+
/>
|
|
28
|
+
|
|
29
|
+
{{-- db version
|
|
30
|
+
|
|
31
|
+
<x-common.table
|
|
32
|
+
title="Recent Orders"
|
|
33
|
+
:headers="['Product', 'Price', 'Date', 'Status']"
|
|
34
|
+
:rows="$orders->map(fn($o) => [
|
|
35
|
+
'product' => $o->product_name,
|
|
36
|
+
'price' => 'Rp ' . number_format($o->price),
|
|
37
|
+
'date' => $o->close_date->format('d M Y'),
|
|
38
|
+
'status' => $o->status,
|
|
39
|
+
])"
|
|
40
|
+
/> --}}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
</x-common.component-card>
|
|
44
|
+
|
|
45
|
+
@endsection
|