improve
parent
61efcdb870
commit
e6d86840c1
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CategoriesQuery extends Controller
|
||||
{
|
||||
public function __invoke(Request $request)
|
||||
{
|
||||
if ($request->q != null) {
|
||||
return Category::where('name', 'like', '%'.$request->q.'%')->limit(10)->get();
|
||||
}
|
||||
return Category::limit(10)->get();
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Laravel\Telescope\IncomingEntry;
|
||||
use Laravel\Telescope\Telescope;
|
||||
use Laravel\Telescope\TelescopeApplicationServiceProvider;
|
||||
|
||||
class TelescopeServiceProvider extends TelescopeApplicationServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
// Telescope::night();
|
||||
|
||||
$this->hideSensitiveRequestDetails();
|
||||
|
||||
Telescope::filter(function (IncomingEntry $entry) {
|
||||
if ($this->app->environment('local')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $entry->isReportableException() ||
|
||||
$entry->isFailedRequest() ||
|
||||
$entry->isFailedJob() ||
|
||||
$entry->isScheduledTask() ||
|
||||
$entry->hasMonitoredTag();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent sensitive request details from being logged by Telescope.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function hideSensitiveRequestDetails()
|
||||
{
|
||||
if ($this->app->environment('local')) {
|
||||
return;
|
||||
}
|
||||
|
||||
Telescope::hideRequestParameters(['_token']);
|
||||
|
||||
Telescope::hideRequestHeaders([
|
||||
'cookie',
|
||||
'x-csrf-token',
|
||||
'x-xsrf-token',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Telescope gate.
|
||||
*
|
||||
* This gate determines who can access Telescope in non-local environments.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function gate()
|
||||
{
|
||||
Gate::define('viewTelescope', function ($user) {
|
||||
return in_array($user->email, [
|
||||
//
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
use Laravel\Telescope\Http\Middleware\Authorize;
|
||||
use Laravel\Telescope\Watchers;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Telescope Domain
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the subdomain where Telescope will be accessible from. If the
|
||||
| setting is null, Telescope will reside under the same domain as the
|
||||
| application. Otherwise, this value will be used as the subdomain.
|
||||
|
|
||||
*/
|
||||
|
||||
'domain' => env('TELESCOPE_DOMAIN', null),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Telescope Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the URI path where Telescope will be accessible from. Feel free
|
||||
| to change this path to anything you like. Note that the URI will not
|
||||
| affect the paths of its internal API that aren't exposed to users.
|
||||
|
|
||||
*/
|
||||
|
||||
'path' => env('TELESCOPE_PATH', 'telescope'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Telescope Storage Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This configuration options determines the storage driver that will
|
||||
| be used to store Telescope's data. In addition, you may set any
|
||||
| custom options as needed by the particular driver you choose.
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => env('TELESCOPE_DRIVER', 'database'),
|
||||
|
||||
'storage' => [
|
||||
'database' => [
|
||||
'connection' => env('DB_CONNECTION', 'mysql'),
|
||||
'chunk' => 1000,
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Telescope Master Switch
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option may be used to disable all Telescope watchers regardless
|
||||
| of their individual configuration, which simply provides a single
|
||||
| and convenient way to enable or disable Telescope data storage.
|
||||
|
|
||||
*/
|
||||
|
||||
'enabled' => env('TELESCOPE_ENABLED', true),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Telescope Route Middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These middleware will be assigned to every Telescope route, giving you
|
||||
| the chance to add your own middleware to this list or change any of
|
||||
| the existing middleware. Or, you can simply stick with this list.
|
||||
|
|
||||
*/
|
||||
|
||||
'middleware' => [
|
||||
'web',
|
||||
Authorize::class,
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Allowed / Ignored Paths & Commands
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following array lists the URI paths and Artisan commands that will
|
||||
| not be watched by Telescope. In addition to this list, some Laravel
|
||||
| commands, like migrations and queue commands, are always ignored.
|
||||
|
|
||||
*/
|
||||
|
||||
'only_paths' => [
|
||||
// 'api/*'
|
||||
],
|
||||
|
||||
'ignore_paths' => [
|
||||
'nova-api*',
|
||||
],
|
||||
|
||||
'ignore_commands' => [
|
||||
//
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Telescope Watchers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following array lists the "watchers" that will be registered with
|
||||
| Telescope. The watchers gather the application's profile data when
|
||||
| a request or task is executed. Feel free to customize this list.
|
||||
|
|
||||
*/
|
||||
|
||||
'watchers' => [
|
||||
Watchers\BatchWatcher::class => env('TELESCOPE_BATCH_WATCHER', true),
|
||||
Watchers\CacheWatcher::class => env('TELESCOPE_CACHE_WATCHER', true),
|
||||
Watchers\ClientRequestWatcher::class => env('TELESCOPE_CLIENT_REQUEST_WATCHER', true),
|
||||
|
||||
Watchers\CommandWatcher::class => [
|
||||
'enabled' => env('TELESCOPE_COMMAND_WATCHER', true),
|
||||
'ignore' => [],
|
||||
],
|
||||
|
||||
Watchers\DumpWatcher::class => env('TELESCOPE_DUMP_WATCHER', true),
|
||||
|
||||
Watchers\EventWatcher::class => [
|
||||
'enabled' => env('TELESCOPE_EVENT_WATCHER', true),
|
||||
'ignore' => [],
|
||||
],
|
||||
|
||||
Watchers\ExceptionWatcher::class => env('TELESCOPE_EXCEPTION_WATCHER', true),
|
||||
|
||||
Watchers\GateWatcher::class => [
|
||||
'enabled' => env('TELESCOPE_GATE_WATCHER', true),
|
||||
'ignore_abilities' => [],
|
||||
'ignore_packages' => true,
|
||||
],
|
||||
|
||||
Watchers\JobWatcher::class => env('TELESCOPE_JOB_WATCHER', true),
|
||||
Watchers\LogWatcher::class => env('TELESCOPE_LOG_WATCHER', true),
|
||||
Watchers\MailWatcher::class => env('TELESCOPE_MAIL_WATCHER', true),
|
||||
|
||||
Watchers\ModelWatcher::class => [
|
||||
'enabled' => env('TELESCOPE_MODEL_WATCHER', true),
|
||||
'events' => ['eloquent.*'],
|
||||
'hydrations' => true,
|
||||
],
|
||||
|
||||
Watchers\NotificationWatcher::class => env('TELESCOPE_NOTIFICATION_WATCHER', true),
|
||||
|
||||
Watchers\QueryWatcher::class => [
|
||||
'enabled' => env('TELESCOPE_QUERY_WATCHER', true),
|
||||
'ignore_packages' => true,
|
||||
'slow' => 100,
|
||||
],
|
||||
|
||||
Watchers\RedisWatcher::class => env('TELESCOPE_REDIS_WATCHER', true),
|
||||
|
||||
Watchers\RequestWatcher::class => [
|
||||
'enabled' => env('TELESCOPE_REQUEST_WATCHER', true),
|
||||
'size_limit' => env('TELESCOPE_RESPONSE_SIZE_LIMIT', 64),
|
||||
'ignore_status_codes' => [],
|
||||
],
|
||||
|
||||
Watchers\ScheduleWatcher::class => env('TELESCOPE_SCHEDULE_WATCHER', true),
|
||||
Watchers\ViewWatcher::class => env('TELESCOPE_VIEW_WATCHER', true),
|
||||
],
|
||||
];
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,5 @@
|
||||
{
|
||||
"/app.js": "/app.js?id=d3ff915bff3de87b87cc",
|
||||
"/app-dark.css": "/app-dark.css?id=3ae28ef5f7b987d68dc6",
|
||||
"/app.css": "/app.css?id=7c970f699ed9cf60d80b"
|
||||
}
|
@ -0,0 +1,215 @@
|
||||
/*
|
||||
Select Input Common React Component
|
||||
Inspired By: react-select , https://codepen.io/dixie0704/pen/jOVxGXL, and others
|
||||
Created By: Aji Kamaludin <aji19kamaludin@gmail.com>
|
||||
*/
|
||||
|
||||
import React, { useRef, useEffect, useState } from 'react'
|
||||
import { useDebounce } from '@/Hooks'
|
||||
|
||||
export default function CategorySelectInput(props) {
|
||||
const { value = '', onItemSelected = null, disabled = false, createNew = null, invalid = false} = props
|
||||
|
||||
const ref = useRef()
|
||||
|
||||
const [showItems, setShowItem] = useState([])
|
||||
|
||||
const [isSelected, setIsSelected] = useState(true)
|
||||
const [selected, setSelected] = useState(value)
|
||||
const [query, setQuery] = useState('')
|
||||
const q = useDebounce(query, 300)
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const toggle = () => {
|
||||
setIsSelected(false)
|
||||
setQuery('')
|
||||
setIsOpen(!isOpen)
|
||||
}
|
||||
|
||||
const onInputMouseDown = () => {
|
||||
setIsSelected(false)
|
||||
setQuery('')
|
||||
setIsOpen(true)
|
||||
}
|
||||
|
||||
const handleSelectItem = (item) => {
|
||||
setIsSelected(true)
|
||||
onItemSelected(item)
|
||||
setSelected(item.name)
|
||||
setIsOpen(false)
|
||||
}
|
||||
|
||||
const filterItems = (value) => {
|
||||
setIsSelected(false)
|
||||
setQuery(value)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const checkIfClickedOutside = (e) => {
|
||||
if (isOpen && ref.current && !ref.current.contains(e.target)) {
|
||||
setIsOpen(false)
|
||||
}
|
||||
}
|
||||
document.addEventListener('mousedown', checkIfClickedOutside)
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', checkIfClickedOutside)
|
||||
}
|
||||
}, [isOpen])
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
fetch(`${route('api.categories.query')}?q=${q}`)
|
||||
.then((res) => res.json())
|
||||
.then((json) => {
|
||||
setShowItem(json)
|
||||
})
|
||||
.catch((err) => {
|
||||
alert(err)
|
||||
})
|
||||
.finally(() => setLoading(false))
|
||||
}, [q])
|
||||
|
||||
useEffect(() => {
|
||||
setSelected('')
|
||||
}, [disabled])
|
||||
|
||||
useEffect(() => {
|
||||
setSelected(value)
|
||||
}, [value])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center" ref={ref}>
|
||||
<div className="w-full flex flex-col items-center">
|
||||
<div className="w-full">
|
||||
<div className="flex flex-col items-center relative">
|
||||
<div className="w-full">
|
||||
<div
|
||||
className={`my-2 p-1 bg-white flex border rounded-lg
|
||||
${
|
||||
invalid
|
||||
? 'border-red-500'
|
||||
: 'border-gray-300'
|
||||
}
|
||||
${disabled ? 'bg-gray-50' : ''}`}
|
||||
>
|
||||
<input
|
||||
className="p-1 px-2 appearance-none outline-none w-full text-gray-800"
|
||||
onMouseDown={onInputMouseDown}
|
||||
placeholder="select category..."
|
||||
value={isSelected ? selected : query}
|
||||
onChange={(e) => filterItems(e.target.value)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<div onClick={disabled ? () => {} : toggle}>
|
||||
<button className="cursor-pointer w-6 h-6 text-gray-600 outline-none focus:outline-none">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="100%"
|
||||
height="100%"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
{isOpen ? (
|
||||
<polyline points="18 15 12 9 6 15"></polyline>
|
||||
) : (
|
||||
<polyline points="18 15 12 20 6 15"></polyline>
|
||||
)}
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{isOpen && (
|
||||
<div
|
||||
className="absolute shadow-lg bg-white top-100 z-40 w-full lef-0 rounded overflow-y-auto"
|
||||
style={{ maxHeight: '300px', top: '100%' }}
|
||||
>
|
||||
<div className="flex flex-col w-full">
|
||||
{loading ? (
|
||||
<div>
|
||||
<div className="flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative hover:border-neutral-content">
|
||||
<div className="w-full items-center justify-center flex">
|
||||
<div className="mx-2 my-5">
|
||||
<span>Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{createNew !== null && (
|
||||
<div
|
||||
className="bordered"
|
||||
onClick={createNew}
|
||||
>
|
||||
<div className="flex w-full items-center justify-center p-2 pl-2 border-transparent border-l-2 relative hover:bg-gray-600 hover:text-white">
|
||||
<div className="w-full items-center justify-center flex space-x-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={
|
||||
2
|
||||
}
|
||||
d="M12 9v3m0 0v3m0-3h3m-3 0H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<div>New</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{showItems.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
onClick={() =>
|
||||
handleSelectItem(item)
|
||||
}
|
||||
>
|
||||
<div className="flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative hover:border-neutral-content hover:bg-gray-300">
|
||||
<div className="w-full items-center flex">
|
||||
<div className="mx-2">
|
||||
<span>
|
||||
{item.name}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{showItems.length <= 0 && (
|
||||
<div>
|
||||
<div className="flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative hover:border-neutral-content">
|
||||
<div className="w-full items-center justify-center flex">
|
||||
<div className="mx-2 my-5">
|
||||
<span>
|
||||
No Items Found
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -0,0 +1,178 @@
|
||||
/*
|
||||
Select Input Common React Component
|
||||
Inspired By: react-select , https://codepen.io/dixie0704/pen/jOVxGXL, and others
|
||||
Created By: Aji Kamaludin <aji19kamaludin@gmail.com>
|
||||
*/
|
||||
|
||||
import React, { useRef, useEffect, useState } from 'react'
|
||||
|
||||
export default function SelectInput(props) {
|
||||
const ref = useRef()
|
||||
|
||||
const items = [
|
||||
'rahayuheni3@gmail.com',
|
||||
'inovacell04@gmail.com',
|
||||
'Btg33@gmail.com',
|
||||
'nikolampo96@gmail.com',
|
||||
'grinaldifoc@gmail.com',
|
||||
'nienha_tj26@yahoo.com',
|
||||
'rizkitriwhyuni139@gmail.com',
|
||||
'wahyu.saputro6982@gmail.com',
|
||||
'fariyath315@gmail.com',
|
||||
'suryaningsihworo@gmail.com',
|
||||
'andiyanayudi@gmail.com',
|
||||
'hoshos2303@gmail.com',
|
||||
'emailnaontehiyeu@gmail.com',
|
||||
'surahmanomez@gmail.com',
|
||||
'mmainah172@gmail.com',
|
||||
'kiosbuuyun@gmail.com',
|
||||
]
|
||||
|
||||
const [showItems, setShowItem] = useState(items)
|
||||
const [selected, setSelected] = useState('')
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [createNew] = useState(true)
|
||||
const disable = false
|
||||
|
||||
const toggle = () => {
|
||||
setSelected('')
|
||||
setShowItem(items)
|
||||
setIsOpen(!isOpen)
|
||||
}
|
||||
|
||||
const onInputMouseDown = () => {
|
||||
setSelected('')
|
||||
setShowItem(items)
|
||||
setIsOpen(true)
|
||||
}
|
||||
|
||||
const handleSelectItem = (item) => {
|
||||
setSelected(item)
|
||||
setIsOpen(false)
|
||||
}
|
||||
|
||||
const filterItems = (value) => {
|
||||
setSelected(value)
|
||||
setShowItem(items.filter(item => item.toLowerCase().includes(value)))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const checkIfClickedOutside = (e) => {
|
||||
if (isOpen && ref.current && !ref.current.contains(e.target)) {
|
||||
setIsOpen(false)
|
||||
}
|
||||
}
|
||||
document.addEventListener('mousedown', checkIfClickedOutside)
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', checkIfClickedOutside)
|
||||
}
|
||||
}, [isOpen])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center" ref={ref}>
|
||||
<div className="w-full flex flex-col items-center">
|
||||
<div className="w-full">
|
||||
<div className="flex flex-col items-center relative">
|
||||
<div className="w-full">
|
||||
<div className="my-2 p-1 bg-white flex border border-gray-300 rounded-lg">
|
||||
<input
|
||||
className="p-1 px-2 appearance-none outline-none w-full text-gray-800"
|
||||
onMouseDown={onInputMouseDown}
|
||||
placeholder="select category..."
|
||||
value={selected}
|
||||
onChange={(e) => filterItems(e.target.value)}
|
||||
disabled={disable}
|
||||
/>
|
||||
<div
|
||||
onClick={disable ? () => {} : toggle}
|
||||
className={`text-gray-300 w-8 py-1 pl-2 pr-1 border-l flex items-center border-gray-200 ${
|
||||
disable ? 'bg-gray-50' : ''
|
||||
}`}
|
||||
>
|
||||
<button className="cursor-pointer w-6 h-6 text-gray-600 outline-none focus:outline-none">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="100%"
|
||||
height="100%"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
{isOpen ? (
|
||||
<polyline points="18 15 12 9 6 15"></polyline>
|
||||
) : (
|
||||
<polyline points="18 15 12 20 6 15"></polyline>
|
||||
)}
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{isOpen && (
|
||||
<div
|
||||
className="absolute shadow-lg bg-white top-100 z-40 w-full lef-0 rounded overflow-y-auto"
|
||||
style={{ maxHeight: '300px', top: '100%' }}
|
||||
>
|
||||
<div className="flex flex-col w-full">
|
||||
{createNew && (
|
||||
<div className="bordered">
|
||||
<div className="flex w-full items-center justify-center p-2 pl-2 border-transparent border-l-2 relative hover:bg-gray-600 hover:text-white">
|
||||
<div className="w-full items-center justify-center flex space-x-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M12 9v3m0 0v3m0-3h3m-3 0H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<div>New</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{showItems.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
onClick={() => handleSelectItem(item)}
|
||||
>
|
||||
<div className="flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative hover:border-neutral-content hover:bg-gray-300">
|
||||
<div className="w-full items-center flex">
|
||||
<div className="mx-2">
|
||||
<span>{item}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{showItems.length <= 0 && (
|
||||
<div>
|
||||
<div className="flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative hover:border-neutral-content">
|
||||
<div className="w-full items-center justify-center flex">
|
||||
<div className="mx-2 my-5">
|
||||
<span>
|
||||
No Items Found
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
export function useDebounce(value, delay) {
|
||||
const [debouncedValue, setDebouncedValue] = useState(value)
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedValue(value)
|
||||
}, delay)
|
||||
return () => {
|
||||
clearTimeout(handler)
|
||||
}
|
||||
}, [value, delay])
|
||||
return debouncedValue
|
||||
}
|
Loading…
Reference in New Issue